home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Diamond Collection / The Diamond Collection (Software Vault)(Digital Impact).ISO / cdr13 / nfbtr731.zip / NFBTRANS.C < prev    next >
C/C++ Source or Header  |  1995-01-24  |  119KB  |  4,460 lines

  1. /*nfbtrans.c converted from Pascal to C by Randy formenti N8KL*/
  2. /*Ammended to by Brian Buhrow in order to use under the Unix operating
  3. system*/
  4. #ifndef unix
  5. #define LINT_ARGS
  6. #define DOS
  7. #endif           /* unix */
  8. #ifndef lint
  9. #endif           /* lint */
  10. #include    <stdio.h>
  11. #include <sys/types.h>
  12. #include <sys/stat.h>
  13. #ifdef DOS
  14. #include <io.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include <ctype.h>
  18. #include <fcntl.h>
  19. #include <conio.h>
  20. #include <dos.h>
  21. #include <memory.h>
  22. #include <process.h>
  23. #else
  24. #include <string.h>
  25. #include <fcntl.h>
  26. #endif           /* DOS */
  27. #include <time.h>
  28. #include <signal.h>
  29. #include <errno.h>
  30.  
  31. #ifdef unix
  32. #define CONFIG_FILE "nfbtrans.cnf"      /* For us Unix types who hate
  33.                      * uppercase */
  34. #define MAXPATHLEN 1023 /* For the longest possible pathname */
  35. #define O_BINARY 0 /* We don't need it here */
  36. /*Definition of mode bits for open*/
  37. #ifndef S_ISUID    /* If we've seen this before, no redefinition */
  38. #define S_ISUID 04000    /* set User id on execution */
  39. #define S_ISGID 02000    /* set Group id on execution */
  40. #define S_ISVTX 01000    /* save text image after termination */
  41. #define S_IREAD 00400    /* read by owner */
  42. #define S_IWRITE 00200    /* write by owner */
  43. #define S_IEXEC 00100    /* execute by owner */
  44. #endif           /* The following are not usually defined */
  45. #define STD_OPEN 00777    /* rwxrwxrwx */
  46. #define delay(a) delay_unix(a)
  47. #define FOPEN_READ "r"
  48. #define FOPEN_WRITE "w"
  49. #else           /* DOS */
  50. #define CONFIG_FILE "NFBTRANS.CNF"      /* For those DOS heades */
  51. #define STD_OPEN S_IWRITE    /* Standard DOs open */
  52. #define MAXPATHLEN 127    /* for the longest possible path name in DOS */
  53. #define FOPEN_READ "rt"
  54. #define FOPEN_WRITE "wt"
  55. #endif           /* unix */
  56.  
  57. #ifdef _S_IFCHR
  58. #define IFCHR _S_IFCHR
  59. #elif defined(S_IFCHR)
  60. #define IFCHR S_IFCHR
  61. #else
  62. #define IFCHR _IFCHR
  63. #endif
  64.  
  65. /*defines and defaults*/
  66. #define     VERSION     "Version 7.31, \nJanuary 24, 1995"
  67. #define COPYRIGHT "Written by the National Federation of the Blind and Randy \
  68. Formenti"
  69. #define MAX_MATCH 15
  70. #define MAX_REP 10
  71. #define MAXTAB        1200    /* number of entries in binary table of
  72.                  * braille rules */
  73. #define TABLENAME "braille.tab" /* for DOS or Unix */
  74. #define MAX_FILES 50    /* max # of files stored using wildcard spec in dos */
  75. #define MAX_EXTENSIONS 40    /* # of extensions for auto format */
  76. #define MAX_INIT 45/* max length of pre_init & post_init strings */
  77. #define MAX_TOKENS 40    /* max # of token on a line of .efl file */
  78. #define MAXWORDLEN 132
  79. #define MAX_TOC_ENTRY 200
  80. #define MAX_EFL_DATA 40
  81. #define MAX_EFL_DATA_LEN 40
  82. #define MAX_COL_WIDTH 20    /* in table definition */
  83. #define TRUE 1
  84. #define FALSE 0
  85. #define BUFSIZE 2048
  86. #define GRADE0 0
  87. #define GRADE1 1
  88. #define GRADE2 2
  89. #define GRADE3 3
  90. #define POETRY 1
  91. # define TEXT 2
  92. #define BLOCK 3
  93. #define LISTS 4
  94. #define BLOCK_PARA 5
  95. #define AUTO_FORMAT 6
  96. #define UPPER 2
  97. #define LOWER 1
  98. #define NUMERIC 4
  99. #define NOTRANS 8
  100.  
  101. /*global variables*/
  102. char temp[160];
  103. int paramcount;
  104. char **paramstr;
  105. char *options[67] =/* all allowed options alphabetically */
  106. {"CA", "CL", "CO", "CS", "DB", "DE", "DS", "EF", "ET", "EX", "FP", "FS", "GD",
  107.   "GM", "HE", "HK", "I0", "I1", "I2", "I3", "I4", "I5", "I6", "I7", "I8",
  108.   "I9", "IA", "IB", "IC", "ID", "IE", "IP", "IT", "KC", "L0", "L1", "LE", "LF",
  109.   "LI", "LM", "LS", "MM", "NC", "OW", "PA", "PD", "PE", "PF", "PL", "PN", "PS",
  110.   "PW", "QM", "RW", "S0", "SI", "SO", "SP", "ST", "TD", "TF", "TM", "TN", "TP",
  111. "TV", NULL};
  112. char *main_menu[3] = {
  113.   "  1 - Translate a Text File\n",
  114.   "  2 - Emboss a File that has already been Translated\n",
  115. "  3 - Back Translate a Grade Two file\n"};
  116. char *call_prefix[13] =
  117. {"KA", "KB", "KC", "KD", "KE", "K", "N", "WA", "WB", "WD", "W", "VE", NULL};
  118. char single_dot[5] = {"@,'\042"};
  119. char prn[13] = {"prn"};
  120. char stdin_name[13] = {"stdin"};
  121. char *progress[2] = {"Skipping", "On"};
  122. char *token_names[19] = /* used in external format language */
  123. {"D", "T", "L", "SK", "C", "IND", "PAG", "FIE", "O", "ST", "A", "MAT",
  124. "REPL", "REPS*", "REPS", "REPW*", "REPW", NULL};
  125. short token_vals[19] =    /* values for tokens above */
  126. {1, 2, 3, 4, 5, 6, 80, 100, 101, 102, 199, 202, 301, 305, 306, 310, 311, 999};
  127. char *stateid[60] =
  128. {"AK\000Alaska", "AL\000Alabama", "AR\000Arkansas",
  129.   "AZ\000Arizona", "AS\000American Samoa", "CA\000California",
  130.   "CO\000Colorado", "CT\000Connecticut", "CZ\000Canal Zone",
  131.   "DC\000District of Columbia", "DE\000Delaware", "FL\000Florida",
  132.   "GA\000Georgia", "GU\000Guam", "HI\000Hawaii",
  133.   "ID\000Idaho", "IL\000Ilinois", "IN\000Indiana",
  134.   "IA\000Iowa",
  135.   "KS\000Kansas", "KY\000Kentucky", "LA\000Lousiana", "ME\000Maine",
  136.   "MD\000Maryland", "MA\000Massachusetts", "MI\000Michigan",
  137.   "MN\000Minnesota", "MS\000Mississippi", "MO\000Missouri",
  138.   "MT\000Montana", "NE\000Nebraska", "NV\000Nevada",
  139.   "NH\000New Hampshire", "NJ\000New Jersey", "NM\000New Mexico",
  140.   "NY\000New York", "NC\000North Carolina", "ND\000North Dakota",
  141.   "CN\000Northern Mariana Is", "OH\000Ohio", "OK\000Oklahoma",
  142.   "OR\000Oregon", "PA\000Pennsylvania", "PR\000Puerto Rico",
  143.   "RI\000Rhode Island", "SC\000South Carolina", "SD\000South Dakota",
  144.   "TN\000Tennessee", "TT\000Trust Territories", "TX\000Texas",
  145.   "UT\000Utah", ",VT\000Vermont", "VA\000Virginia",
  146.   "VI\000Virgin Islands", "WA\000Washington", "WV\000West Virginia",
  147. "Wi\000Wisconsin", "WY\000Wyoming", NULL};
  148.  
  149. typedef short BOOL;
  150.  
  151. /*globals for buffered read*/
  152. char iobuf[BUFSIZE + 1];
  153. unsigned int bytes_in_buf;
  154. char *ioptr, *eolptr;
  155. short timer = 0xe00;    /* default delay timing value only if linked with
  156.              * nfbasm.asm */
  157. short emboss_delay = 0;
  158. short hot_key = 0; /* no hot keys by default */
  159. short max_menu = 2;/* 2 options printed on main menu */
  160. short ab_flag = 0; /* abort */
  161. short it_flag = 0;
  162. short stdin_tty = 0, stdout_tty = 0;    /* is stdin or stdout 1 keyboard or 0
  163.                      * file */
  164. short print_date = 0, print_file = 0;    /* prints date and file on first page
  165.                      * if true */
  166. short toc_pages[MAX_TOC_ENTRY];
  167. short toc_page, current_pass;
  168. short spool = 0, charspersec = 40;
  169. short keep_together = 0, keep_together_save = 0;
  170. short prog_init;
  171. short file_count, current_file, total_files = 0;
  172. struct tm *tm;
  173.  
  174. typedef struct
  175. {
  176.   unsigned short startline, endline;
  177.   BOOL lflag;
  178.   short fopstart, fopend, dummy;
  179. }   loptype;
  180.  
  181. typedef struct
  182. {
  183.   short fop;       /* operation */
  184.   short fstart;    /* field start */
  185.   short flen;       /* field length */
  186.   short fappo;       /* pointer to data */
  187. }   foptype;
  188.  
  189. typedef struct
  190. {           /* holds binary form of braille rules */
  191.   short start1[256];
  192.   short start2[27][27];
  193.   short typex[MAXTAB + 1];
  194.   char match[MAXTAB + 1][MAX_MATCH + 1];
  195.   char replace[MAXTAB + 1][MAX_REP + 1];
  196. }   tablet;
  197.  
  198. typedef struct
  199. {
  200.   char ext[10];
  201.   short init_val;
  202. }   extension_t;
  203.  
  204. typedef struct
  205. {
  206.   short total;
  207.   extension_t prog_ext[MAX_EXTENSIONS];
  208. }   prog_ext_t;
  209. prog_ext_t prog_extension;
  210.  
  211. typedef struct
  212. {
  213.   char pre_init[MAX_INIT + 1], post_init[MAX_INIT + 1], format[3];
  214. }   init_t;
  215. init_t init[15];   /* for i0 - i9 */
  216.  
  217. typedef char columnt[MAX_COL_WIDTH + 1];
  218.  
  219. BOOL usr_default = FALSE;
  220. short pagestart = 0, pagestart_save, pageend = -1, pageend_save;
  221. char field_[256];
  222. char *field = field_;
  223. short count, copies, lastcopy = 0, rejoin, quiet_mode = 0;
  224. short bpagec, pagenumlen, read_hyphen_file;
  225. char token[MAX_TOKENS][40];
  226. short token_count, token_char;
  227. short current_token;
  228. short fopcount, lopcount;
  229. short lineskips = 99, linesperpage = 25;
  230. short maxline = 0, make_sound = 1;
  231. short display_braille = -1;
  232. short display_source = -1;
  233. BOOL printit = TRUE;
  234. short skip_output = 0, over_write = 0, input_file_arg = 0, start_arg = 1;
  235. short graphics_mode = 0;    /* skip chars with b7 set */
  236. short guide_dots = 2;
  237. short keep_control = 0, expand_tab = 0;
  238. short table_entries;
  239. BOOL no_copyright = FALSE;    /* display copyright by default */
  240. short leftmargin = -1;
  241. short capvec[256], subvec[256];
  242. short trans_mode = -1, trans_default = 21;
  243. short pause_time = 0, inf_path_len = 0;
  244. unsigned long total_words, total_dots[8], total_cells, total_lines, emboss_time;
  245. time_t time1, time2;
  246. long in_length, out_length, total = 0l, total_rejoins;
  247. short efl_mode = FALSE;
  248. BOOL reload_table = TRUE;
  249. char inf_name[MAXPATHLEN] = {0};
  250. char inf_name_ext[10];
  251. char file_name[MAX_FILES][13];
  252. char hyphen_file[40], hyphen_extension[5] = {".hyp"};
  253. int outf_des = 0;
  254. FILE *intext = NULL, *lfile, *hyp_ptr, *conf_ptr;
  255. int inf_des, inf_des_save = 0;
  256. char outf_name[49] = {0};
  257. char efl_file[49];
  258. foptype f[40];
  259. char efl_data[MAX_EFL_DATA][MAX_EFL_DATA_LEN + 1];
  260. short appcount, linecount;
  261. BOOL lopactive = FALSE;
  262. unsigned short inpglen = 66;    /* input page length */
  263. char transpath[MAXPATHLEN + 1] = {0};
  264. char table_file[MAXPATHLEN + 1];
  265. char stat_file[MAXPATHLEN + 1] = {0};
  266. char config_file[MAXPATHLEN] = {CONFIG_FILE};
  267. char indent[30] = {"  "};
  268. char format_string[4] = {"~"};
  269. char date_string[20];
  270. char *dayofweek[7] = {"sun", "mon", "tue", "wed", "thu", "fri", "sat"};
  271. char s0_init[20] = {0};
  272. char l0[4] = {0};
  273. char l1[4] = {0};
  274. char table_definition[40] = {0}, table_sscan[25] = {"%s %s %s %s %s %s %s %s"};
  275. char italics = '_';
  276. char cap_single[4] = {","};
  277. char cap_all[4] = {",,"};
  278. char quotes[8] = {"8080"};
  279. short field_width[8];
  280. short cols_in_table, cols_in_line, chars_in_table, chars_in_line;
  281. loptype l[40];
  282. unsigned char dot_table[128] = {    /* braille dot equivilent for each
  283.                      * ascii char, used in statistics
  284.                      * file */
  285.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,    /* ascii 0-15 b0 = dot
  286.                              * 1, b1 = dot 2 ... */
  287.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,    /* ascii 16-31 */
  288.   0, 46, 16, 60, 43, 41, 47, 4, 55, 62, 33, 44, 32, 36, 40, 12, /* / ascii 32-47 */
  289.   52, 2, 6, 18, 50, 34, 22, 54, 38, 20, 49, 48, 35, 63, 28, 57, /* ? ascii 48-63 */
  290.   8, 65, 67, 73, 89, 81, 75, 91, 83, 74, 90, 69, 71, 77, 93, 75,    /* @-O */
  291.   79, 95, 87, 78, 94, 101, 103, 122, 109, 125, 117, 42, 51, 59, 24, 56, /* _ */
  292.   0, 1, 3, 9, 25, 17, 11, 27, 19, 10, 26, 5, 7, 13, 29, 21,    /* 96-o */
  293.   15, 31, 23, 14, 30, 37, 39, 58, 45, 61, 53, 0, 0, 0, 0, 0,    /* p-127 */
  294. };
  295.  
  296. unsigned char graph_tab[170] = {
  297.   /* converts ascii representation of braille to ibm graphic characters */
  298.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,    /* ascii 0-15 */
  299.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,    /* ascii 16-31 */
  300.   32, 221, 189, 163, 196, 211, 219, 0, 224, 208, 220, 201, 190, 173, 251, 175,    /* 32-47 ' */
  301.   162, 172, 0, 186, 174, 206, 161, 0, 191, 170, 215, 223, 0, 198, 193, 212,    /* 63 27< */
  302.   0, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, /* 64-79 @ */
  303.   240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 188, 197, 252, 253    /* 80-95 */
  304. };
  305.  
  306. columnt *column = (columnt *) & graph_tab[0];    /* graph_tab unused for now */
  307. char bnumber[] = {"jabcdefghi"};        /* lowercase for 8 dot braille */
  308. tablet b;
  309. /*variables for do_translate*/
  310. BOOL done;
  311. char oldword[200];
  312. char oldline[256], oldline6[256];
  313. char tline[256];
  314. char fline[256];
  315. char hline[256];
  316. char bline[256];
  317. char bline6[256];
  318. char wline[256];
  319. short blinec, bpageb, bpageh, linelength, fill_length;
  320. short center_length = 30;
  321. short first_page = FALSE;
  322. short curmax;
  323.  
  324. unsigned char c;
  325. char words[200];
  326. char bword[200];
  327. char bword6[200];
  328.  
  329. BOOL join;
  330. BOOL group;
  331. BOOL pjoin;
  332. BOOL pgroup;
  333. BOOL xjoin;
  334. BOOL xgroup;
  335. BOOL xpjoin;
  336. BOOL xpgroup;
  337.  
  338. int xgrade = -1, grade_mod = 0;
  339. BOOL xcenter, find_toc_pages, got_toc_page, last_toc_word = FALSE;
  340. short xformat = -1, xformat_save;
  341. short blank_lines;
  342. BOOL xdouble, xtab, xacronym, xheading, xfooting, makefoot, makehead, fillit;
  343.  
  344. BOOL quoteopen, quoteclose;
  345.  
  346. short margin, point, firstletter, chardec, lastmatch;
  347. char linein[256], *plinein, line_end[4] = {0};
  348. unsigned short lineinct;
  349. BOOL newline;
  350. short quotecount;
  351. BOOL dopagenum = -1;
  352. BOOL doroman, dobook;
  353. unsigned char tabtable[256];
  354. BOOL disablecol;
  355. short setmargin, oldmargin;
  356. BOOL tabmargin;
  357. BOOL pageset;
  358. char addchar[11];
  359. short actualpage;
  360. short interpoint = FALSE;
  361. char *roman[10] =
  362. {"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"};
  363. char *roman10[10] = {"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"};
  364. struct stat infilestat, outfilestat;
  365.  
  366. #ifdef DOS
  367. struct find_t fileinfo; /* wildcard support for dos */
  368. #endif           /* DOS */
  369.  
  370. /*function prototypes*/
  371. void top_of_form(void);
  372. void page_beep(void);
  373. void backspace_int(short);
  374. void dofillit(void);
  375. void make_roman(void);
  376. void make_arabic(short *);
  377. void make_book(void);
  378. void bpurge(void);
  379. void format_first_line(void);
  380. void build_line(void);
  381. void flush_if_not_blank(void);
  382. void add_case(void);
  383. void add_dots(char *);
  384. short get_integer(char *);
  385. void get_digit(void);
  386. void get_date(void);
  387. void do_commands(void);
  388. void do_lop_op(foptype);
  389. void do_lop(void);
  390. void getline(void);
  391. void get_input(char *, short);
  392. void get_paragraph_type(void);
  393. void check_purge(void);
  394. void get_word(void);
  395. void set_vect(void);
  396. void do_letter(void);
  397. void do_number(void);
  398. void do_punct(void);
  399. void build_word(void);
  400. void check_ham_call(void);
  401. void trans_word(void);
  402. BOOL store_next_token(void);
  403. void pop_token(char *);
  404. short check_token(void);
  405. void store_commands(void);
  406. void add_efl_data(char *);
  407. void test_range(char *);
  408. void load_template(void);
  409. void do_translate(void);
  410. void write_stat_file(void);
  411. void advance_page(void);
  412. void load_tables(void);
  413. void translate_file(void);
  414. int open_input_file(void);
  415. void report_open_error(void);
  416. short test_file_exist(void);
  417. void backtranslate_file(void);
  418. short test_extension(char *);
  419. short search_extensions(char *);
  420. #ifndef __TURBOC__
  421. void delay(int);
  422. void sound(int);
  423. void nosound(void);
  424. #endif
  425. void emboss_file(void);
  426. void spool_file(void);
  427. void get_copies(void);
  428. void get_page_range(void);
  429. void get_config(void);
  430. void process_options(char *);
  431. void process_table_definition(void);
  432. void trim(char *);
  433. short strpos(char *, char *);
  434. void insert(char *, char *);
  435. void move(char *, char *, short);
  436. void do_pause(void);
  437. void get_printer_file_name(void);
  438. void pause_program(void);
  439. short check_keyboard(short);
  440. void write_string(char *, short);
  441. void write_char(char);
  442. void no_space(void);
  443. void sort_names(void);
  444. void copy_string(char *, char *, short);
  445. void cleanup(int);
  446. void exit_program(int);
  447. void print_error(char *,...);
  448. int ISalpha(char);
  449. void main(int, char **);
  450. #ifdef unix
  451. extern char *strlwr(char *string);
  452. extern char *strupr(char *string);
  453. extern short getch(void);
  454. extern short getche(void);
  455. extern long filelength(int descriptor);
  456. extern short beep(int count);
  457. extern short kbhit(void);
  458. extern void get_tablename(char *string);
  459. #endif           /* unix */
  460.  
  461. void top_of_form()
  462. {
  463.   short i;
  464.   BOOL dopagesave = dopagenum;
  465.   if (bpagec >= pageend)
  466.   {
  467.     done = TRUE;
  468.     bline[0] = bline6[0] = bword[0] = 0;
  469.     return;
  470.   }
  471.   actualpage++;
  472.   bpagec++;
  473.   if (bpagec > pagestart)
  474.   {           /* page in range */
  475.     if (lineskips < 99)
  476.       for (i = 0; i < lineskips + linesperpage - blinec; i++)
  477.     write_string(" ", 1);
  478.     else
  479.     {
  480.       if (lineskips == 99)
  481.     write_char(12); /* formfeed */
  482.       else
  483.       {
  484.     if (lineskips == 999)
  485.       write_string("\13", 0);
  486.     else
  487.     if (lineskips == 9999)
  488.     {       /* 9999 */
  489.       write_string("\14", 0);
  490.       fprintf(stderr, "\nPress Any Key to Continue\7");
  491.       getch();
  492.     }       /* 9999 */
  493.       }
  494.     }
  495.   }           /* page in range */
  496.   blinec = 0;
  497.   keep_together = keep_together_save;
  498.   if (done == FALSE || xfooting == TRUE)
  499.   {           /* next page */
  500.     pagenumlen = 0;
  501. /*if interpoint mode do not print even page numbers*/
  502.     if (interpoint && (bpagec & 1) == 0)
  503.       dopagenum = FALSE;
  504.     if (dopagenum && ((bpagec > 1 - (first_page > 0)) || pageset) && !xheading)
  505.     {           /* adjust for page number */
  506.       pagenumlen = (short) (4 + (bpagec > 9) + (bpagec > 99));
  507.       linelength = curmax - pagenumlen - margin - (short) strlen(addchar);
  508.     }           /* adjust for page number */
  509.     else
  510.       linelength = curmax + 1 - margin;
  511.     if (xcenter)
  512.       linelength = center_length;
  513.     dopagenum = dopagesave;
  514.     page_beep();
  515.     if (display_braille)
  516.     {           /* display_braille */
  517.       sprintf(wline, "Copy %d of %d   page %d", copies, lastcopy, bpagec);
  518.       strcpy(temp, wline);
  519.       i = ((short) strlen(wline) - maxline) >> 1;
  520.       if (i > 0)
  521.       {
  522.     memset(field, 32, maxline);
  523.     strnset(field, '*', i);
  524.     field[i] = 0;
  525.     sprintf(wline, "%s%s%s", field, temp, field);
  526.       }
  527.       if (!skip_output)
  528.     fprintf(stderr, "%s\n", wline);
  529.     }           /* display_braille */
  530.     else
  531.     if (skip_output + quiet_mode == 0)
  532.     {           /* report progress */
  533.       sprintf(temp, "%s page %d", progress[(bpagec >= pagestart)], bpagec);
  534.       if (lastcopy > 1)
  535.     sprintf(temp + strlen(temp), " Copy %d of %d", copies,
  536.         lastcopy);
  537.       fprintf(stderr, "%s\n", temp);
  538.     }           /* report progress */
  539.  
  540.     if (printit)
  541.       delay(emboss_delay);
  542.   }           /* next page */
  543.   else
  544.     bpagec--;
  545. }           /* top_of_form */
  546.  
  547. void page_beep()
  548. {
  549.   if (make_sound)
  550.   {
  551. #ifndef unix
  552.     sound(2000);
  553.     delay(4);
  554.     nosound();
  555. #else
  556.     beep(1);       /* Beep terminal */
  557. #endif           /* unix */
  558.   }
  559. }           /* page_beep */
  560.  
  561. void backspace_int(short j)
  562. {           /* output a packspace so cursor is at first number of
  563.             * integer */
  564.   do
  565.   {
  566.     j /= 10;
  567.     fprintf(stderr, "%c", 8);
  568.   }
  569.   while (j > 0);
  570. }           /* backspace_int */
  571.  
  572. void dofillit()
  573. {
  574.   int i, j;
  575.   fillit = FALSE;
  576.   i = strlen(bline) - 1;
  577.   if (got_toc_page)
  578.   {           /* add page number to bline */
  579.     bline[curmax] = 0;
  580.     make_arabic(&toc_page);
  581.     i += 2;
  582.     sprintf(bline + i - 1, " %s", field);
  583.   }           /* add page number to bline */
  584.   else
  585.   {           /* process last word on line */
  586.     if (i <= 0)
  587.       return;
  588.     /* find out where last word on bline begins */
  589.     while (bline[i] != ' ' && i > 0)
  590.       i--;
  591.     if (bline[i] == ' ')
  592.       i++;
  593.     strcpy(field, bline + i);    /* store the last word of bline */
  594.     if ((short) strlen(field) >= fill_length)
  595.       print_error("\007Last word %s of TOC longer than %d characters in line %ld\n",
  596.           field, fill_length - 1, total_lines);
  597.   }           /* process last word on line */
  598.   memset(bline + i, '\42', maxline - i);        /* fill with quotes dot 5 */
  599.   j = maxline - i - strlen(field) - 1;
  600.   if (j < guide_dots)
  601.     memset(bline + i, ' ', j);  /* remove guide dots */
  602.   i = maxline - strlen(field);
  603.   strcpy(bline + i, field);
  604.   bline[i - 1] = ' ';   /* put blank before last word */
  605. }           /* dofillit */
  606.  
  607. void make_roman()
  608. {
  609.   if (bpagec >= 100)
  610.     make_arabic(&bpagec);
  611.   else
  612.     sprintf(field, ";%s%s", roman10[bpagec / 10], roman[bpagec % 10]);
  613. }           /* make_roman */
  614.  
  615. void make_arabic(short *page)
  616. {
  617.   short i;
  618.   sprintf(field, "#%d", *page);
  619.   i = 1;
  620.   while (field[i])
  621.   {
  622.     field[i] = bnumber[(short) (field[i] - (char) 48)];
  623.     i++;
  624.   }           /* while */
  625.   if (page == &bpagec)
  626.     strcat(field, addchar);
  627. }           /* make_arabec */
  628.  
  629. void make_book()
  630. {
  631.   field++;       /* make room for possible character at beginning */
  632.   make_arabic(&bpageb);
  633.   field--;       /* put pointer back where it was */
  634.   if (bpagec - bpageh > 1)
  635.     field[0] = (char) ((int) ('A') + bpagec - 2 - bpageh);
  636.   else
  637.     strcpy(field, field + 1);    /* remove first char of field */
  638. }           /* make_book */
  639.  
  640. void bpurge()
  641. {
  642.   short j, guide_line = 0;
  643.   BOOL dopagesave = dopagenum;
  644.   char ch;
  645.   blinec++;       /* increment current braille line */
  646.   if (bline[0])
  647.   {           /* bline not empty */
  648.     if (strlen(bline6) > strlen(bline))
  649.       strcpy(bline, bline6);
  650.     ch = bline[curmax];
  651.     bline[curmax] = 0;    /* set bline to <curmax chars long */
  652.  
  653.     if (margin > 1)
  654.     {           /* insert space before left margin */
  655.       move(bline, bline + margin - 1, curmax + 1 - margin);
  656.       /* insert space in front of line if necessary */
  657.       memset(bline, 32, margin - 1);    /* fill in left margin with spaces */
  658.     }           /* insert space before left margin */
  659.   }           /* bline not empty */
  660.  
  661.   if (xcenter)
  662.   {           /* center */
  663.     trim(bline);
  664.     j = (curmax - (short) strlen(bline)) >> 1;
  665.     if (j > 0)
  666.     {
  667.       move(bline, bline + j, (short) strlen(bline));
  668.       memset(bline, 32, j);
  669.     }
  670.     if (newline)
  671.       xcenter = FALSE;
  672.   }           /* center */
  673.  
  674.   if (fillit && newline)
  675.   {
  676.     bline[curmax] = ch;
  677.     dofillit();
  678.     guide_line = 1;/* line of toc with dot 5 guidemarks */
  679.   }
  680.  
  681.   if (blinec == 1)
  682.   {           /* first line on this page */
  683.     field[0] = 0;
  684.     if (interpoint && (bpagec & 1) == 0)
  685.       dopagenum = FALSE;    /* no even page numbers for interpoint */
  686.     if (((bpagec > 1 - (first_page > 0)) || pageset || dobook) && dopagenum)
  687.     {           /* store braille page number in field */
  688.       if (doroman)
  689.     make_roman();
  690.       else
  691.       if (dobook)
  692.     make_book();
  693.       else
  694.     make_arabic(&bpagec);
  695.       if (guide_line || (table_definition[0] && chars_in_table + pagenumlen > curmax))
  696.       {        /* cannot have this line on a line with a page number */
  697.     strcpy(bline6, bline);
  698.     bline[0] = 0;
  699.     format_first_line();
  700.     if (bpagec >= pagestart)
  701.       write_string(bline, 1);
  702.     field[0] = 0;
  703.     strcpy(bline, bline6);
  704.     blinec++;
  705.       }        /* cannot have this line on a page number line */
  706.     }           /* store braille page number in field */
  707.     dopagenum = dopagesave;
  708.     if (xheading)
  709.     {           /* xheading */
  710.       strcpy(hline + strlen(hline) - strlen(field), field);
  711.       if (bpagec >= pagestart)
  712.     write_string(hline, 1);
  713.       blinec++;
  714.     }           /* xheading */
  715.     else
  716.       format_first_line();
  717.   }           /* first line on page */
  718.   else
  719.   if (keep_together)
  720.   {           /* conditional skip & not first line */
  721.     /* find out if bline has only spaces */
  722.     strcpy(field, bline);
  723.     trim(field);
  724.     if (!field[0] && blinec + keep_together > linesperpage)
  725.     {           /* skip rest of page */
  726.       blinec--;
  727.       top_of_form();
  728.       return;
  729.     }           /* skip rest of page */
  730.   }           /* conditional skip & not first line */
  731.  
  732.   if (dobook && blinec >= linesperpage)
  733.   {           /* put braille page in lower right corner */
  734.     make_arabic(&bpagec);
  735.     j = (short) strlen(bline);
  736.     memset(bline + j, 32, maxline - j);
  737.     strcpy(bline + maxline - strlen(field), field);
  738.   }           /* put braille page number in lower right corner. */
  739.  
  740.   if (bpagec >= pagestart)
  741.   {           /* output */
  742.     write_string(bline, 1);
  743.     if (xdouble)
  744.     {           /* double space */
  745.       write_string(" ", 1);
  746.       blinec++;
  747.     }           /* double space */
  748.   }           /* output */
  749.  
  750.   bline[0] = bline6[0] = 0;
  751.   if (!(xformat == TEXT) || fillit)
  752.     strcpy(bline, indent);
  753.   if (xformat == BLOCK || xformat == BLOCK_PARA)
  754.     bline[0] = '\0';
  755.   strcpy(bline6, bline);
  756.   pjoin = FALSE;
  757.   pgroup = FALSE;
  758.   if (xfooting && (blinec >= linesperpage - 1))
  759.   {           /* put footing on bottom of current page */
  760.     if (dobook)
  761.     {           /* adjust footing for braille page in lower right corner */
  762.       make_arabic(&bpagec);
  763.       strcpy(oldline, fline);    /* save fline */
  764.       strcpy(fline, fline + strlen(field) + 1);
  765.       sprintf(fline + strlen(fline), " %s", field);
  766.     }           /* adjust footing for braille page in lower right corner */
  767.     if (bpagec >= pagestart)
  768.       write_string(fline, 1);
  769.     if (dobook)
  770.       strcpy(fline, oldline);
  771.     blinec++;
  772.   }           /* put footing on bottom of current page */
  773.   if (blinec >= linesperpage)
  774.     top_of_form();
  775.   else
  776.   if (dobook && (blinec >= linesperpage - 1) && !xfooting)
  777.     linelength = curmax - 6 - margin;
  778.   else
  779.     linelength = curmax + 1 - margin;
  780.   if (xcenter)
  781.     linelength = center_length;
  782.   newline = FALSE;
  783. }           /* bpurge */
  784.  
  785. void format_first_line()
  786. {
  787.   short j;
  788.   j = (short) strlen(bline);
  789.   memset(bline + j, 32, maxline - j);
  790.   strcpy(bline + maxline - strlen(field), field);
  791. }           /* format_first_line */
  792.  
  793. void build_line()
  794. {
  795.   short i, j, l, r, build_bpurge = 0;
  796.   i = (short) strlen(bline);
  797.   if (xtab)
  798.   {           /* xtab */
  799.     j = r = 0;
  800.     do
  801.     {
  802.       r++;
  803.       if (tabtable[i + r] != 0)
  804.     j = r;       /* found tab */
  805.     }
  806.     while (j == 0 && (i + r < linelength));
  807.  
  808.     if (!j)
  809.       j = 1;
  810.     for (r = 1; r < j; r++)
  811.     {
  812.       strcat(bline, " ");
  813.       strcat(bline6, " ");
  814.     }
  815.     pjoin = pgroup = xtab = FALSE;
  816.   }           /* xtab */
  817.  
  818.   if (l1[0] && strcmp(words, l1) == 0)
  819.     pjoin = TRUE;
  820.  
  821.   if (!(pjoin || (pgroup && group)))
  822.     i++;       /* account for space */
  823.   j = i + (short) strlen(bword6);
  824.   i += (short) strlen(bword);
  825.  
  826.   if (i > linelength || j > linelength)
  827.     build_bpurge++;
  828.   if (l0[0])
  829.     if (strchr(l0, words[strlen(words + 1)]))
  830.       join = TRUE;
  831.   if (fillit)
  832.   {           /* fillit */
  833.     if (i > linelength - fill_length || j > linelength - fill_length)
  834.       build_bpurge++;
  835.     if (last_toc_word)
  836.       build_bpurge = FALSE;
  837.   }           /* fillit */
  838.   if (build_bpurge)
  839.     if (bline[0] && strcmp(bline, indent))
  840.       bpurge();
  841.  
  842.   if (pjoin || (pgroup && group) || (strcmp(bword, "1") == 0 && xgrade > 0)
  843.       || (bline[0] == '\0'))
  844.   {
  845.     sprintf(bline6, "%s%s", bline, bword6);
  846.     strcat(bline, bword);
  847.   }
  848.   else
  849.   {
  850.     r = (short) strlen(bline);
  851.     if (bline[r - 1] == ' ')
  852.     {
  853.       sprintf(bline6, "%s%s", bline, bword6);
  854.       strcat(bline, bword);
  855.     }
  856.     else
  857.     {
  858.       sprintf(bline6, "%s %s", bline, bword6);
  859.       sprintf(bline + r, " %s", bword);
  860.     }
  861.   }
  862.  
  863.   if (last_toc_word)
  864.   {           /* output toc line */
  865.     last_toc_word = FALSE;
  866.     newline = TRUE;
  867.     bpurge();
  868.   }           /* output toc line */
  869.  
  870.   if (table_definition[0] && plinein >= eolptr)
  871.   {           /* table defined & last word on line */
  872.     sscanf(bline, table_sscan, column[0], column[1],
  873.        column[2], column[3], column[4], column[5], column[6], column[7]);
  874.     for (i = 0; i < cols_in_table; i++)
  875.     {
  876.       if ((short) strlen(column[i]) > field_width[i])
  877.     print_error("\007Field %d > %d characters in line %ld\n", i + 1,
  878.             field_width[i], total_lines);
  879.       if (column[i][0] == '`' && column[i][1] == '\0')
  880.     column[i][0] = 0;    /* have a column with blanks */
  881.     }           /* i */
  882.     sprintf(bline, table_definition, column[0], column[1], column[2],
  883.         column[3], column[4], column[5], column[6], column[7]);
  884.     bpurge();
  885.   }           /* table defined & last word on line */
  886.  
  887.   if (!strcmp(bline, "BE"))
  888.     if (xgrade > 1)
  889.       strcpy(bline, "2");       /* braille for be */
  890.   bword6[0] = '\0';
  891.   pgroup = group;
  892.   pjoin = join;
  893.   r = (short) strlen(bline);
  894.   l = curmax - (blinec == 0) * pagenumlen;
  895.   if (r > l)
  896.   {           /* line too long */
  897.     /* look for repeating characters */
  898.     j = 0;
  899.     c = bline[0];
  900.     for (i = 1; bline[i]; i++)
  901.       if (bline[i] == c)
  902.     j++;
  903.       else
  904.       {        /* no repeat */
  905.     j = 0;
  906.     c = bline[i];
  907.       }        /* no repeat */
  908.     if (r - j < l)
  909.     {           /* truncate repeats */
  910.   truncate:
  911.       if (bline[0] == ' ')
  912.     strcpy(bline, bline + strlen(indent));
  913.       bline[l] = '\0';
  914.       bpurge();
  915.       return;
  916.     }           /* truncate repeats */
  917.     else
  918.     {           /* line still too long */
  919.       /* look for double repeats */
  920.       i = (short) (r - 3);
  921.       while (i >= 0)
  922.     if (bline[i] == bline[r - 1] && bline[i - 1] == bline[r - 2])
  923.       i -= 2;
  924.     else
  925.       break;
  926.       if (i + 3 < l)
  927.     goto truncate;
  928.       /* no double repeate so continue on next line */
  929.       strcpy(bword, bline + l);
  930.       bline[l] = bword6[0] = '\0';
  931.       build_line();
  932.     }           /* word still too long */
  933.   }           /* line too long */
  934. }           /* build_line */
  935.  
  936. void flush_if_not_blank()
  937. {
  938.   short i;
  939.   for (i = 0; bline[i]; i++)
  940.     if (bline[i] != ' ')
  941.     {           /* line contains a nonblank character */
  942.       bpurge();
  943.       break;
  944.     }           /* line contains a nonblank character */
  945. }           /* flush_if_not_blank */
  946.  
  947. short get_integer(char *string)
  948. {           /* returns integer from string and removes digits. 18hello
  949.             * becomes hello returning 18 */
  950.   short j = 0, retval = 0, minusflag = 0;
  951.   if (string[0] == '-')
  952.   {
  953.     minusflag = 1;
  954.     j++;
  955.   }
  956.   while (isdigit(string[j]))
  957.   {
  958.     retval = 10 * retval + (short) (string[j] - (char) 48);
  959.     j++;
  960.   }           /* while */
  961.   if (j - minusflag)
  962.     strcpy(string, string + j); /* remove digits */
  963.   return (retval);
  964. }           /* get_integer */
  965.  
  966. void get_digit()
  967. {
  968.   if (hot_key)
  969.   {
  970.     temp[1] = 0;
  971.     temp[0] = (char) getche();
  972.     if (temp[0] <= '\r')
  973.       temp[0] = 0;
  974.     if (temp[0] == (char) 27)
  975.     {           /* escape */
  976.       fprintf(stderr, "\n");
  977.       exit_program(0);
  978.     }           /* escape */
  979.   }
  980.   else
  981.     get_input(temp, 80);
  982. }           /* get_digit */
  983.  
  984. void get_date()
  985. {           /* stores date in date_string */
  986.   time(&time1);
  987.   tm = localtime(&time1);
  988.   sprintf(date_string, "%s %02d/%02d/%02d %02d:%02d",
  989.       dayofweek[tm->tm_wday], tm->tm_mon + 1, tm->tm_mday, tm->tm_year,
  990.       tm->tm_hour, tm->tm_min);
  991. }           /* get_date */
  992.  
  993. void add_dots(char *string)
  994. {
  995.   int dot, i = 0, j;
  996.   while (string[i])
  997.   {
  998.     dot = dot_table[(int) string[i]];
  999.     if (xgrade)
  1000.       dot &= 63;   /* remove dot 7 unless we're doing computer braille */
  1001.     total_cells++;
  1002.     for (j = 0; j < 7; j++)
  1003.     {
  1004.       if (dot & 1)
  1005.     total_dots[j]++;
  1006.       dot = dot >> 1;
  1007.     }           /* j */
  1008.     i++;
  1009.   }           /* while */
  1010. }           /* add_dots */
  1011. void add_case()
  1012. {
  1013.   short i, j = 0, k;
  1014.   BOOL show_caps = TRUE, show_lower = FALSE;
  1015.   for (i = 0; words[i]; i++)
  1016.   {
  1017.     if (isupper(words[i]) && show_caps)
  1018.     {           /* add comma */
  1019.       bword[j++] = ',';
  1020.       if (isupper(words[i + 1]))
  1021.       {        /* add another comma */
  1022.     bword[j++] = ',';
  1023.     show_caps = FALSE;
  1024.     show_lower = TRUE;
  1025.       }        /* add another comma */
  1026.     }           /* add a comma */
  1027.     if (islower(words[i]) && show_lower)
  1028.     {
  1029.       bword[j++] = ';';
  1030.       show_lower = FALSE;
  1031.       show_caps = TRUE;
  1032.     }
  1033.     if (words[i] < ' ')
  1034.     {
  1035.       k = b.start1[(int) words[i]];
  1036.       strcpy(bword + j, b.replace[k]);
  1037.       j += (short) (strlen(b.replace[k]));
  1038.       continue;
  1039.     }
  1040.     bword[j++] = words[i];
  1041.   }           /* i */
  1042.   bword[j] = 0;
  1043. }           /* add_case */
  1044.  
  1045. void do_commands()
  1046. {
  1047.   short tilpos, i, j, k, l, grade_modified = 0;
  1048.   char c, *cptr;
  1049.   if ((cptr = strpbrk(words, format_string)) == NULL)
  1050.     return;       /* no format commands in word */
  1051.   /* assume command will be forced to a new braille line */
  1052.   newline = TRUE;
  1053.  
  1054.   tilpos = 1 + (short) (cptr - words);
  1055.   if (words[tilpos])    /* theres a character after the tilda */
  1056.     do
  1057.     {
  1058.       c = (char) toupper(words[tilpos]);    /* the character after the ~ */
  1059.       cptr = words + tilpos - 1;
  1060.       if (!strchr("ILZ[", c))
  1061.     strcpy(cptr, cptr + 2); /* for every char except ILZ[ */
  1062.       if (strchr("CEFMSTY[_", c))
  1063.     flush_if_not_blank();
  1064.  
  1065.       switch (c)
  1066.       {
  1067.       case 'A':   /* Acronym Logic - Betty Desimone */
  1068.     xacronym = TRUE;
  1069.     newline = FALSE;
  1070.     break;
  1071.       case 'B':   /* Textbook Break */
  1072.     doroman = FALSE;
  1073.     dobook = TRUE;
  1074.     bpageh = bpagec;    /* set to current page */
  1075.     /* blinec is 0 if first line has not been written to page */
  1076.     if (blinec < linesperpage)
  1077.       bpageh--;
  1078.     bpageb = get_integer(cptr);
  1079.     if (!bpageb)
  1080.       bpageb = 1;    /* set to 1 if invalid integer */
  1081.     flush_if_not_blank();
  1082.     memset(tline, '-', maxline);    /* dots 3/6 */
  1083.     i = maxline;
  1084.     make_arabic(&bpageb);
  1085.     strcpy(tline + maxline - strlen(field), field); /* put page num at end
  1086.                              * of line */
  1087.     if (blinec > 1 && blinec < linesperpage - 1)
  1088.     {       /* not at top 2 or bottom 2 lines of page */
  1089.       if (bpagec >= pagestart)
  1090.         write_string(tline, 1);
  1091.       blinec++;
  1092.     }       /* not at top 2 or bottom 2 lines of page */
  1093.     else
  1094.       linelength = curmax - 6 - margin;
  1095.     break;
  1096.       case 'C':   /* Center */
  1097.     xcenter = TRUE;
  1098.     if (center_length > (short) (curmax - 6))
  1099.       center_length = (short) (curmax - 6);
  1100.     linelength = center_length;
  1101.     break;
  1102.       case 'D':   /* Double Toggle */
  1103.     xdouble ^= xdouble;
  1104.     break;
  1105.       case 'E':   /* Poetry */
  1106.     xformat = POETRY;
  1107.     break;
  1108.       case 'F':   /* Fill Line - Index table of contents */
  1109.     fillit = TRUE;
  1110.     /* assume a normal ~f not followed by digit */
  1111.     got_toc_page = FALSE;
  1112.     if (isdigit(*cptr))
  1113.     {       /* process toc mark */
  1114.       i = get_integer(cptr);
  1115.       if (i > MAX_TOC_ENTRY)
  1116.         print_error("\007More than %d TOC entries not allowed\n", MAX_TOC_ENTRY);
  1117.       if (current_pass == 1)
  1118.       {       /* first pass */
  1119.         if (!i)
  1120.         {       /* one pass required before embossing */
  1121.           if (find_toc_pages)
  1122.         goto duplicate;
  1123.           /*
  1124.            * set starting and ending page so program translates entire
  1125.            * file but never writes to disk during first pass
  1126.            */
  1127.           pagestart = pageend = 32767;
  1128.           find_toc_pages = TRUE;
  1129.           fillit = FALSE;
  1130.           break;
  1131.         }       /* one pass required before embossing */
  1132.         /* in first pass with i in range */
  1133.         if (!find_toc_pages)
  1134.           print_error("\007~f0 not found before ~F%d on line %ld\n",
  1135.               i + 1, total_lines);
  1136.         if (toc_pages[i - 1] > 0)
  1137.       duplicate:print_error("\007Duplicate ~f%d entry on line %ld\n", i, total_lines);
  1138.         if (!toc_pages[i - 1])
  1139.         {       /* toc entry on first pass */
  1140.           toc_pages[i - 1] = -1;    /* found first toc mark */
  1141.           got_toc_page = TRUE;    /* page is correct only on second
  1142.                      * pass */
  1143.         }       /* toc entry on first pass */
  1144.         else
  1145.         {       /* found second toc mark first pass */
  1146.           toc_pages[i - 1] = bpagec;
  1147.           fillit = FALSE;    /* title, not actual toc entry */
  1148.         }       /* second toc entry first pass */
  1149.       }       /* first pass */
  1150.       else
  1151.       {       /* second pass */
  1152.         if (!i)
  1153.         {       /* ~f0 second pass */
  1154.           fillit = FALSE;
  1155.           break;
  1156.         }       /* ~f0 second pass */
  1157.         if (toc_pages[i - 1])
  1158.         {       /* first toc entry second pass */
  1159.           toc_page = toc_pages[i - 1];
  1160.           toc_pages[i - 1] = 0;    /* indicates this contents/title pair
  1161.                      * has been processed */
  1162.           got_toc_page = TRUE;
  1163.         }       /* first toc entry second pass */
  1164.         else
  1165.           fillit = FALSE;    /* title not toc entry */
  1166.       }       /* second pass */
  1167.     }       /* process toc entry */
  1168.     else
  1169.     if (*cptr == ':')
  1170.     {       /* colen */
  1171.       strcpy(cptr, cptr + 1);
  1172.       fill_length = get_integer(cptr);
  1173.     }       /* colen */
  1174.     break;
  1175.       case 'G':   /* Set Right Margin */
  1176.     i = curmax;
  1177.     curmax = get_integer(cptr);
  1178.     if (curmax < 1)
  1179.       curmax = 1;
  1180.     if (curmax > maxline)
  1181.       curmax = maxline;
  1182.     linelength = curmax + 1 - margin;
  1183.     break;
  1184.  
  1185.       case 'H':   /* Heading */
  1186.     strcpy(oldline, bline);
  1187.     strcpy(oldline6, bline6);
  1188.     xheading = TRUE;
  1189.     xpgroup = pgroup;
  1190.     xpjoin = pjoin;
  1191.     xjoin = join;
  1192.     xgroup = group;
  1193.     makehead = TRUE;
  1194.     bline[0] = 0;
  1195.     bline6[0] = 0;
  1196.     pgroup = FALSE;
  1197.     group = FALSE;
  1198.     join = FALSE;
  1199.     pjoin = FALSE;
  1200.     break;
  1201.       case 'I':   /* Italics */
  1202.     words[tilpos] = italics;
  1203.     if (words[tilpos + 1] == '\\')
  1204.     {
  1205.       it_flag ^= 1;
  1206.       strcpy(words + tilpos + 1, words + tilpos + 2);
  1207.     }
  1208.     else
  1209.       it_flag = 0;
  1210.     if (tilpos > 1)
  1211.     {       /* >=1 char before ~ */
  1212.       if (isalpha(words[tilpos - 2]))
  1213.         words[tilpos - 1] = '-';
  1214.       else
  1215.         strcpy(words + tilpos - 1, words + tilpos);
  1216.     }
  1217.     else
  1218.     {
  1219.       words[tilpos - 1] = italics;
  1220.       if (!it_flag)
  1221.         strcpy(words + tilpos - 1, words + tilpos);
  1222.     }
  1223.     newline = FALSE;
  1224.     break;
  1225.       case 'J':   /* Stop Heading */
  1226.     xheading = FALSE;
  1227.     break;
  1228.       case 'K':   /* Stop Footing */
  1229.     xfooting = FALSE;
  1230.     break;
  1231.       case 'L':   /* Letter Sign */
  1232.     words[tilpos - 1] = '|';        /* don't translate next character */
  1233.     words[tilpos] = ';';
  1234.     /* newline=FALSE;  */
  1235.     break;
  1236.       case 'M':   /* Left Margin Set */
  1237.     i = margin;
  1238.     margin = get_integer(cptr);
  1239.     if (margin < 1)
  1240.       margin = 1;
  1241.     if (margin > 30)
  1242.       margin = 30;
  1243.     linelength += i - margin;
  1244.     setmargin += margin - oldmargin;
  1245.     oldmargin = margin;
  1246.     break;
  1247.  
  1248.       case 'N':   /* Set PageNum */
  1249.     addchar[0] = 0;
  1250.     dopagenum = TRUE;
  1251.     doroman = FALSE;
  1252.     bpagec = get_integer(cptr);
  1253.     if (isupper(words[0]))
  1254.     {       /* uppercase letter followed number */
  1255.       sprintf(addchar, ";%c", words[0]);
  1256.       words[0] = 0;
  1257.     }       /* uppercase letter followed word */
  1258.     if (bpagec == 1)
  1259.       pageset = TRUE;
  1260.     bpageh = bpagec;
  1261.     if (blinec == 0)
  1262.       linelength = curmax - 6 - margin - (short) strlen(addchar);
  1263.     break;
  1264.       case 'O':   /* Offset for Wrap */
  1265.     i = get_integer(cptr);
  1266.     if (i >= 30)
  1267.       i = 2;   /* keep values reasonable */
  1268.     memset(indent, 32, i);
  1269.     indent[i] = '\0';
  1270.     break;
  1271.       case 'P':   /* New page */
  1272.     if (!isdigit(cptr[0]))
  1273.     {       /* always skip page */
  1274.       k = 1;
  1275.       if (cptr[0] == ':')
  1276.       {
  1277.         strcpy(cptr, cptr + 1);
  1278.         i = get_integer(cptr);
  1279.         strcpy(field, bline);
  1280.         trim(field);
  1281.         if (field[0])
  1282.           i++;
  1283.         if (blinec + i < linesperpage)
  1284.           k = -1;    /* no page break */
  1285.       }
  1286.  
  1287.       if (isalpha(cptr[0]))
  1288.       {
  1289.         /* skip to next odd page if interpoint right facing page is odd */
  1290.         if (interpoint && (bpagec & 1))
  1291.           k++;
  1292.         strcpy(cptr, cptr + 1);
  1293.       }
  1294.       for (l = 0; l < k; l++)
  1295.       {
  1296.         if (blinec >= linesperpage - 1)
  1297.           bpurge(); /* last line on page */
  1298.         else
  1299.         {       /* not last line on page */
  1300.           flush_if_not_blank();
  1301.           if (dobook)
  1302.           {
  1303.         /* we have to put page number in lower right corner */
  1304.         j = blinec;
  1305.         for (i = j; i < linesperpage; i++)
  1306.           bpurge();
  1307.           }
  1308.           else
  1309.         top_of_form();
  1310.         }       /* not last line on page */
  1311.       }       /* l */
  1312.     }       /* always skip page */
  1313.     else
  1314.     {       /* conditional skip */
  1315.       keep_together = get_integer(cptr);
  1316.       if (keep_together > linesperpage / 2)
  1317.         keep_together = (short) (linesperpage / 2);
  1318.       keep_together_save = keep_together;
  1319.     }       /* conditional skip */
  1320.     if (words[0] && total_lines > 0l)
  1321.       goto bad_format;
  1322.     break;
  1323.       case 'Q':   /* clear all tabs */
  1324.     memset(tabtable, 0, sizeof(tabtable));
  1325.     break;
  1326.       case 'R':   /* Roman Numerals */
  1327.     doroman = TRUE;
  1328.     dobook = FALSE;
  1329.     break;
  1330.       case 'S':   /* Skip a line */
  1331.     bpurge();
  1332.     break;
  1333.       case 'T':   /* Text Format */
  1334.     xformat = TEXT;
  1335.     strcat(bline, indent);
  1336.     strcpy(bline6, bline);
  1337.     line_end[0] = '\0';
  1338.     break;
  1339.       case 'U':   /* page Numbering Off */
  1340.     addchar[0] = 0;
  1341.     dopagenum = FALSE;
  1342.     break;
  1343.       case 'V':   /* set tab */
  1344.     i = (short) get_integer(words);
  1345.     if (!i)
  1346.       i = 1;
  1347.     if (i >= linelength)
  1348.       print_error("\007Tab set beyond line length in line %d\n",
  1349.               lineinct);
  1350.     tabtable[i] = 1;
  1351.     break;
  1352.       case 'W':   /* Footing */
  1353.     strcpy(oldline, bline);
  1354.     strcpy(oldline6, bline6);
  1355.     xfooting = TRUE;
  1356.     xpgroup = pgroup;
  1357.     xpjoin = pjoin;
  1358.     xjoin = join;
  1359.     xgroup = group;
  1360.     makefoot = TRUE;
  1361.     bline[0] = 0;
  1362.     bline6[0] = 0;
  1363.     pgroup = FALSE;
  1364.     group = FALSE;
  1365.     join = FALSE;
  1366.     pjoin = FALSE;
  1367.     break;
  1368.       case 'X':
  1369.     xtab = TRUE;
  1370.     j = get_integer(cptr);
  1371.     if (j)
  1372.     {
  1373.       for (i = 0; i < j; i++)
  1374.         if ((short) strlen(bline) < linelength)
  1375.           strcat(bline, " ");
  1376.     }
  1377.     else
  1378.       xtab = TRUE;
  1379.     break;
  1380.       case 'Y':
  1381.     xformat = LISTS;    /* TABLE Format */
  1382.     break;
  1383.       case 'Z':   /* Terminator */
  1384.     words[tilpos] = '`';
  1385.     strcpy(words + tilpos - 1, words + tilpos);
  1386.     newline = FALSE;
  1387.     break;
  1388.       case '\47': /* Apostrophe */
  1389.     words[tilpos] = '=';
  1390.     strcpy(words + tilpos - 1, words + tilpos);
  1391.     newline = FALSE;
  1392.     break;
  1393.       case '_':
  1394.     break;
  1395.       case '0':   /* Grade 0 */
  1396.     if (grade_modified++)
  1397.       grade_mod_error:
  1398.       print_error(
  1399.               "\007Two grade modifiers in word not allowed in line %ld", total_lines);
  1400.     newline = FALSE;
  1401.     group = pjoin = FALSE;
  1402.     xgrade = GRADE0;
  1403.     goto test_mod;
  1404.       case '1':   /* Grade 1 */
  1405.     if (grade_modified++)
  1406.       goto grade_mod_error;
  1407.     newline = FALSE;
  1408.     xgrade = GRADE1;
  1409.     break;
  1410.       case '2':   /* Grade 2 */
  1411.     if (grade_modified++)
  1412.       goto grade_mod_error;
  1413.     newline = FALSE;
  1414.     xgrade = GRADE2;
  1415.     load_tables();
  1416.     break;
  1417.       case '3':   /* grade 3 */
  1418.     if (grade_modified++)
  1419.       goto grade_mod_error;
  1420.     newline = FALSE;
  1421.     xgrade = GRADE3;
  1422.     reload_table = TRUE;    /* forced reload */
  1423.     load_tables();
  1424.     reload_table = TRUE;    /* forced reload for next load_tables */
  1425.     test_mod:
  1426.     grade_mod = 0;
  1427.     if (isdigit(words[tilpos - 1]))
  1428.     {
  1429.       grade_mod = (short) (words[tilpos - 1] - (char) 48);
  1430.       strcpy(words + tilpos - 1, words + tilpos);
  1431.     }
  1432.     break;
  1433.       case '4':   /* block */
  1434.     newline = FALSE;
  1435.     xformat = BLOCK;
  1436.     break;
  1437.       case '5':   /* blockparagraphs */
  1438.     newline = FALSE;
  1439.     xformat = BLOCK_PARA;
  1440.     break;
  1441.       case '6':   /* auto format */
  1442.     newline = FALSE;
  1443.     xformat = AUTO_FORMAT;
  1444.     break;
  1445.       case '[':   /* escape */
  1446.     i = (short) (tilpos - 1);
  1447.     words[i] = (char) 27;    /* escape character */
  1448.     strcpy(words + tilpos, words + tilpos + 1);    /* remove the [ */
  1449.     do
  1450.     {       /* write escape sequence directly to printer or file */
  1451.       write_char(words[i]);
  1452.       i++;
  1453.     }
  1454.     while (words[i] != '\0' && words[i] != '~');
  1455.     strcpy(words + tilpos - 1, words + i);
  1456.     break;
  1457.       case '-':   /* process as command line option */
  1458.     j = tilpos;
  1459.     while (words[j] && words[j] != '~')
  1460.       j++;
  1461.     strcpy(temp, words + tilpos - 1);
  1462.     strcpy(words + tilpos - 1, words + j);
  1463.     temp[j - tilpos + 1] = '\0';
  1464.     strupr(temp);
  1465.     /* if quoted string, the first quote starts in char 4 xx= */
  1466.     if ((temp[3] == '\042' || temp[3] == '\047') &&
  1467.         (strchr(temp + 4, temp[3]) == NULL))
  1468.       while (plinein < eolptr)
  1469.       {
  1470.         get_word();
  1471.         sprintf(temp + strlen(temp), " %s", words);
  1472.         if (strchr(temp + 4, temp[3]))
  1473.         {
  1474.           words[0] = '\0';
  1475.           break;
  1476.         }
  1477.       }       /* while */
  1478.     process_options(temp);
  1479.     break;
  1480.       case '~':
  1481.     format_string[0] = 0;
  1482.     break;
  1483.       default:
  1484.     bad_format:
  1485.     fprintf(stderr, "\007Format error in ");
  1486.     if (total_lines)    /* error occurred in input file */
  1487.       print_error("line %ld\n%s", total_lines, linein);
  1488.     print_error("i%d=%s|%s\n", prog_init,
  1489.             init[prog_init].pre_init, init[prog_init].post_init);
  1490.       }        /* switch */
  1491.       if (strchr("AL", c) && words[0] == '\0')
  1492.     goto bad_format;
  1493.       if ((cptr = strpbrk(words, format_string)) != NULL)
  1494.     tilpos = 1 + (short) (cptr - words);
  1495.     }
  1496.     while (cptr != NULL);
  1497. }           /* do_commands */
  1498.  
  1499. /*** Execute the Operation ***/
  1500. void do_lop_op(foptype fop)
  1501. {
  1502.   short i, j, k, l;
  1503.   if (fop.fop < 100)
  1504.   {           /* not field match or replace */
  1505.     switch (fop.fop)
  1506.     {
  1507.     case 1:      /* delete */
  1508.       linein[0] = 1;
  1509.       linein[1] = 0;    /* delete but don't count as blank */
  1510.       break;
  1511.     case 2:      /* text */
  1512.       xformat = TEXT;
  1513.       break;
  1514.     case 3:      /* list */
  1515.       xformat = LISTS;
  1516.       break;
  1517.     case 4:      /* skip line */
  1518.       strcpy(linein, "~S ");
  1519.       linein[0] = format_string[0];
  1520.       break;
  1521.     case 5:      /* center */
  1522.       trim(linein);
  1523.       strcpy(field, linein);
  1524.       sprintf(linein, "~C%s", field);
  1525.       linein[0] = format_string[0];
  1526.       break;
  1527.     case 6:      /* indent */
  1528.       setmargin = (short) (oldmargin + 2);
  1529.       break;
  1530.     case 80:      /* page */
  1531.       inpglen = (unsigned short) fop.fstart;
  1532.       break;
  1533.     }           /* switch */
  1534.     return;
  1535.   }           /* not field match or replace */
  1536.   if (!linein[0])
  1537.     return;       /* nothing to do on empty line */
  1538.   if (fop.fop < 300)
  1539.   {           /* field or match */
  1540.     j = (short) strlen(linein);
  1541.     if (j < fop.fstart + 1)
  1542.       for (i = j; i <= fop.fstart; i++)
  1543.     strcat(linein, " ");    /* fill in line so field isn't garbage */
  1544.     strcpy(field, linein + fop.fstart);
  1545.     field[fop.flen] = 0;
  1546.  
  1547.     if (fop.fop < 200)
  1548.     {           /* field state omit append */
  1549.       tabmargin = TRUE;
  1550.       strcpy(linein + fop.fstart, linein + fop.fstart + fop.flen);    /* remove field from
  1551.                                      * linein */
  1552.       trim(field);
  1553.  
  1554.       switch (fop.fop)
  1555.       {        /* switch op */
  1556.       case 101:   /* omit */
  1557.     field[0] = 0;
  1558.     break;
  1559.       case 102:   /* state */
  1560.     if (field[0])
  1561.     {       /* field not empty */
  1562.       for (i = 0; stateid[i]; i++)
  1563.       {       /* i */
  1564.         j = strpos(field, stateid[i]);
  1565.         if (j)
  1566.         {       /* found state abbreviation */
  1567.           strcpy(field + j - 1, field + j + 1);
  1568.           insert(stateid[i] + 3, field + j - 1);
  1569.           break;
  1570.         }       /* found state abbreviation */
  1571.       }       /* i */
  1572.     }       /* field not empty */
  1573.       }        /* switch */
  1574.       if (fop.fappo > 0)
  1575.     strcat(field, efl_data[fop.fappo - 1]);
  1576.       insert(field, linein + fop.fstart);
  1577.       return;
  1578.     }           /* <200 */
  1579.  
  1580. /*process match operations which are the only ones left*/
  1581.     if ((fop.fappo > 0) && (strpos(field, efl_data[fop.fappo - 1]) > 0))
  1582.     {           /* match string is not empty */
  1583.       disablecol = TRUE;
  1584.       switch (fop.fop)
  1585.       {
  1586.       case 201:   /* delete */
  1587.     linein[0] = 0;
  1588.     break;
  1589.       case 202:   /* match */
  1590.     disablecol = TRUE;
  1591.     break;
  1592.       }        /* switch */
  1593.     }           /* match string is not empty */
  1594.   }           /* field or match */
  1595.   if (fop.fop > 300 && fop.fop < 312)
  1596.   {           /* replace */
  1597.     k = 1;
  1598.     if (fop.fop == 305 || fop.fop == 310)
  1599.     {
  1600.       k = 40;
  1601.       fop.fop++;
  1602.     }
  1603.     for (l = 0; l < k; l++)
  1604.     {
  1605.       strcpy(temp, linein);
  1606.       strupr(temp);
  1607.       strcpy(field, efl_data[fop.fappo - 1]);
  1608.       j = strpos(temp, field);
  1609.       if (!j)
  1610.     return;
  1611.       j--;       /* relative to zero */
  1612.       switch (fop.fop)
  1613.       {
  1614.       case 301:   /* replace line */
  1615.     strcpy(linein, efl_data[fop.fappo]);
  1616.     break;
  1617.       case 306:   /* replace substring */
  1618.     strcpy(linein + j, linein + j + strlen(field)); /* remove substring */
  1619.     insert(efl_data[fop.fappo], linein + j);
  1620.     break;
  1621.       case 311:   /* replace word */
  1622.     while (linein[j] != ' ' && j > 0)
  1623.       j--;
  1624.     if (linein[j] == ' ')
  1625.       j++;
  1626.     /* j points to first character of word */
  1627.     i = (short) (j + 1);
  1628.     while (linein[i] != ' ' && linein[i] != '\0')
  1629.       i++;
  1630.     strcpy(linein + j, linein + i); /* remove the word */
  1631.     insert(efl_data[fop.fappo], linein + j);
  1632.     break;
  1633.       }        /* switch */
  1634.     }           /* replace */
  1635.   }           /* l */
  1636. }           /* do_lop_op */
  1637.  
  1638. /*** Do Line Operation Processing -- outer loop ***/
  1639. void do_lop()
  1640. {
  1641.   short i, j;
  1642.   disablecol = FALSE;
  1643.   for (i = 0; i < lopcount; i++)
  1644.     if (l[i].lflag)/* match active */
  1645.       if ((lineinct >= l[i].startline) && (lineinct <= l[i].endline))
  1646.       {        /* line within range */
  1647.     j = l[i].fopstart;
  1648.     do_lop_op(f[j]);
  1649.     if (disablecol)
  1650.       for (j = (short) (l[i].fopstart + 1); j < l[i].fopend; j++)
  1651.         do_lop_op(f[j]);
  1652.       }        /* line within range */
  1653.   if (!disablecol)
  1654.     for (i = 0; i < lopcount; i++)
  1655.       if (!l[i].lflag)
  1656.     if ((lineinct >= l[i].startline) && (lineinct <= l[i].endline))
  1657.       for (j = l[i].fopstart; j < l[i].fopend; j++)
  1658.         do_lop_op(f[j]);
  1659.  
  1660.   if (disablecol)
  1661.     tabmargin = FALSE;
  1662. }           /* do_lop */
  1663.  
  1664. void getline()
  1665. {
  1666.   short i = -1, j;
  1667.   for (;;)
  1668.   {           /* do until line read, line too long, or eof */
  1669.     i++;
  1670.     if (!bytes_in_buf)
  1671.     {           /* empty buffer so fill it up */
  1672.       bytes_in_buf = read(inf_des, iobuf, (unsigned int) BUFSIZE);
  1673.       if (bytes_in_buf <= 0)
  1674.       {        /* eof */
  1675.     done = TRUE;
  1676.     if (i > 0 && c != '\n')
  1677.       done = FALSE; /* file ended without crlf */
  1678.     break;
  1679.       }        /* eof */
  1680.       ioptr = iobuf;
  1681.     }           /* buffer empty so fill it up */
  1682.     c = (char) *ioptr;
  1683.     bytes_in_buf--;
  1684.     ioptr++;
  1685.     if (c >= (unsigned char) 128)
  1686.     {           /* b7 */
  1687.       if (!graphics_mode)
  1688.     goto skip_char;
  1689.       if (graphics_mode == 1)
  1690.     c &= 127;  /* remove b7 */
  1691.     }           /* b7 */
  1692.     if (c == 31)
  1693.       c = '|';
  1694.     if (c == '\10' && i > 0)
  1695.     {           /* backspace */
  1696.       i -= 2;
  1697.       continue;
  1698.     }           /* backspace */
  1699.     if (c == (char) 30)
  1700.     {
  1701.   skip_char:
  1702.       i--;
  1703.       continue;
  1704.     }
  1705.     else
  1706.       linein[i] = c;
  1707.     if (c == '\13' || c == '\14')
  1708.       lineinct = 0;
  1709.     if (c == '\n')
  1710.       break;       /* actual eol */
  1711.     if (c == '\t' && lopactive > 0 && expand_tab > 0)
  1712.     {
  1713.       c = ' ';
  1714.       for (j = 0; j < expand_tab; j++)
  1715.     linein[i++] = ' ';
  1716.       i--;
  1717.     }
  1718.     if (i > 170)
  1719.     {           /* look for word break */
  1720.       if (c == ' ' || i > 250)
  1721.       {
  1722.     total_lines--;
  1723.     break;       /* line too long, end at word */
  1724.       }
  1725.     }           /* look for word break */
  1726.     if (c == '\15')
  1727.       goto space;
  1728.     if (c < ' ' && keep_control == 0)
  1729.   space:linein[i] = ' ';
  1730.     /* remove all control chars */
  1731.   }           /* for */
  1732.   linein[i] = linein[i + 1] = '\0';
  1733.   i--;
  1734.   while (i >= 0 && linein[i] == ' ')
  1735.     linein[i--] = 0;    /* remove trailing spaces */
  1736.   eolptr = linein + i + 1;
  1737.   plinein = &linein[0];
  1738.   if (inpglen > 0 && lineinct > inpglen)
  1739.     lineinct = 0;  /* reset lineinct for next input page. Used by .efl files */
  1740.   lineinct++;
  1741.   total_lines++;
  1742.  
  1743.   if (lopactive)
  1744.     do_lop();
  1745.  
  1746.   if (display_source)
  1747.     printf("=>%s\n", linein);
  1748. }           /* getline */
  1749.  
  1750. void get_input(char *string, short length)
  1751. {           /* gets a line of input from stdin up to length bytes */
  1752.   short l;
  1753.   fgets(string, length, stdin);
  1754.   l = (short) (strlen(string) - 1);
  1755.   if (string[l] == '\n' && l >= 0)
  1756.     string[l] = 0;
  1757. }           /* get_input */
  1758.  
  1759. void get_paragraph_type()
  1760. {
  1761.   short indents = 0, blanks = 0;
  1762.   char prev_char = '\1';
  1763.   short save_disp = display_source;
  1764.   xformat = TEXT;
  1765.   if (stdin_tty == 0 || (infilestat.st_mode & IFCHR))
  1766.     return;
  1767.   display_source = 0, done = FALSE, bytes_in_buf = 0;
  1768.   total_lines = 0;
  1769.   do
  1770.   {
  1771.     getline();
  1772.     if (linein[0])
  1773.     {           /* line not empty */
  1774.       if (prev_char == '\0')
  1775.     blanks++;
  1776.       if (!strncmp(linein, "    ", 4))
  1777.     indents++;
  1778.     }           /* line not empty */
  1779.     prev_char = linein[0];
  1780.   }
  1781.   while (done == FALSE && total_lines < 1000);
  1782.   total_lines = 0l;
  1783.   display_source = save_disp;
  1784.   if (blanks > indents)
  1785.     xformat = BLOCK_PARA;
  1786.   linein[0] = '\0';
  1787. }           /* get_paragraph_type */
  1788.  
  1789. void check_purge(void)
  1790. {           /* see if line should be written */
  1791.   short i, j;
  1792.   BOOL purgit = TRUE;
  1793.   /* flush unless the first leftmargin-1 chars contain a nonspace char */
  1794.   for (i = 0; i < leftmargin; i++)
  1795.     /* Determine whether to flush */
  1796.     if (linein[i] != ' ' && linein[i] != '\0')  /* when reading a new Line */
  1797.       purgit = FALSE;
  1798.  
  1799.   if (xformat == LISTS || xformat == BLOCK)
  1800.     purgit ^= 1;   /* toggle purgit */
  1801.   if (xformat == BLOCK_PARA)
  1802.     if (!linein[0])
  1803.     {           /* blank */
  1804.       if (!blank_lines++)
  1805.     purgit = TRUE;    /* indent since this line is blank */
  1806.       else
  1807.     purgit = FALSE;
  1808.       if (!bline[0])
  1809.     purgit = FALSE;
  1810.     }           /* blank */
  1811.     else
  1812.     {           /* not blank */
  1813.       purgit = FALSE;
  1814.       blank_lines = 0;
  1815.     }           /* not blank */
  1816.  
  1817.   if (disablecol)
  1818.     purgit = TRUE;
  1819.  
  1820.   if (purgit)       /* Check for Indentation */
  1821.   {
  1822.     newline = TRUE;
  1823.     j = -1;
  1824.     for (i = 0; bline[i]; i++)
  1825.       if (bline[i] != ' ')
  1826.     j = i;
  1827.     if (j >= 0 || xformat == BLOCK_PARA)
  1828.       bpurge();
  1829.     bline[0] = 0;
  1830.     if (xformat == TEXT || xformat == BLOCK_PARA)
  1831.       strcat(bline, indent);
  1832.     strcpy(bline6, bline);
  1833.     quotecount = 0;
  1834.     if (tabmargin)
  1835.       margin = setmargin;
  1836.     else
  1837.       margin = oldmargin;
  1838.     tabmargin = FALSE;
  1839.   }
  1840. }           /* check_purge */
  1841.  
  1842. /***   Extract a Word From the     ***/
  1843. /***   Input Text -- check for     ***/
  1844. /***          commands         ***/
  1845. void get_word()
  1846. {
  1847.   char *cptr;
  1848.   int l;
  1849.   xacronym = FALSE;
  1850.  
  1851.   newline = FALSE;
  1852.   while (*plinein == '\0' && !done)
  1853.   {           /* blank line and not eof */
  1854.     /*
  1855.      * line could also be blank because all words were removed from read
  1856.      * buffer
  1857.      */
  1858.     l = strlen(bline);    /* length of pending braille line */
  1859.     if (makefoot)
  1860.     {           /* foot */
  1861.       makefoot = FALSE; /* only do once for each ~w command */
  1862.       memset(fline, 32, curmax);
  1863.       fline[linelength] = 0;
  1864.       if (bline[0])
  1865.     move(bline, fline + linelength - l + 1, (short) (l - 1));
  1866.       strcpy(bline, oldline);
  1867.       strcpy(bline6, oldline6);
  1868.       pgroup = xpgroup;
  1869.       pjoin = xpjoin;
  1870.       join = xjoin;
  1871.       group = xgroup;
  1872.     }           /* foot */
  1873.     if (makehead)
  1874.     {           /* head */
  1875.       /* use bline to consstruct header */
  1876.       makehead = FALSE; /* only do this once for each ~h command */
  1877.       memset(hline, 32, curmax);    /* fill with spaces */
  1878.       hline[curmax] = 0;
  1879.       if (bline[0])
  1880.     move(bline, hline + (linelength - l) / 2, (short) (l - 1));
  1881.       strcpy(bline, oldline);
  1882.       strcpy(bline6, oldline6);
  1883.       pgroup = xpgroup;
  1884.       pjoin = xpjoin;
  1885.       join = xjoin;
  1886.       group = xgroup;
  1887.     }           /* head */
  1888.     getline();
  1889.     check_purge();
  1890.   }           /* blank line and not eof */
  1891.  
  1892.   if (done)
  1893.   {
  1894.     words[0] = 0;
  1895.     return;
  1896.   }
  1897.   while (*plinein == ' ')
  1898.     plinein++;       /* skip leading blanks */
  1899.   cptr = strchr(plinein, ' ');
  1900.   if (cptr)
  1901.   {           /* space found */
  1902.     *cptr = 0;       /* put null at end of word */
  1903.     strncpy(words, plinein, sizeof(words));
  1904.     *cptr = ' ';   /* restore linein */
  1905.     plinein = cptr + 1; /* where to search for next word */
  1906.   }           /* space found */
  1907.   else
  1908.   {           /* word at end of line */
  1909.     strncpy(words, plinein, sizeof(words));
  1910.     plinein += strlen(words);    /* we are done with this line */
  1911.   }           /* word at end of line */
  1912.   if (strpbrk(words, format_string))
  1913.     do_commands();
  1914.   words[MAXWORDLEN] = '\0';     /* words shouldn't be longer than that anyway */
  1915.   /* change words containing string of _ to -, looks better in braille */
  1916.   if (words[0] == '_')
  1917.   {           /* _ */
  1918.     l = 0;
  1919.     while (words[++l] == '_');
  1920.     if (l > 2 && words[l] == '\0')
  1921.       strnset(words, '-', l);
  1922.   }           /* _ */
  1923.   return;
  1924. }           /* get_word */
  1925.  
  1926. void set_vect()
  1927. {           /* set up the vector for the characters in a word */
  1928.   char *wptr = &words[0];
  1929.   short *cap_ptr = &capvec[0], *sub_ptr = &subvec[0];
  1930.   short i;
  1931.   do
  1932.   {
  1933.     *cap_ptr = *sub_ptr = 0;
  1934.     if (*wptr >= '\0')
  1935.     {           /* not graphics character */
  1936.       if (isupper(*wptr))
  1937.     *cap_ptr = UPPER;
  1938.       else
  1939.       {        /* not uppercase */
  1940.     if (islower(*wptr))
  1941.       *cap_ptr = LOWER;
  1942.     else
  1943.     if (*wptr == '|' && format_string[0] != '\0')
  1944.     {       /* vertical bar */
  1945.       strcpy(wptr, wptr + 1);    /* delete | */
  1946.       *cap_ptr = NOTRANS;    /* do not translate character after | */
  1947.       *wptr |= 128; /* set b7 on character not to be trahnslated */
  1948.       /* this prevents this char from being a match in do_letter */
  1949.     }       /* vertical bar */
  1950.       }        /* is not uppercase */
  1951.     }           /* not graphics character */
  1952.     else
  1953.     {           /* graphics character */
  1954.       *cap_ptr = LOWER;
  1955.       i = b.typex[b.start1[(short) (unsigned char) *wptr]];
  1956.       if (graphics_mode == 3 && i == 0)
  1957.     print_error("\007Graphics character %d not in %s line %ld\n",
  1958.             (short) (unsigned char) *wptr, table_file, total_lines);
  1959.       if (i == 29)
  1960.     *cap_ptr = UPPER;
  1961.     }           /* graphics character */
  1962.     wptr++;
  1963.     cap_ptr++;
  1964.     sub_ptr++;
  1965.   }
  1966.   while (*wptr);
  1967.   strupr(words);
  1968.   *cap_ptr = *sub_ptr = 0;
  1969. }           /* set_vect */
  1970.  
  1971. /***   Check the extracted word  ***/
  1972. /*** against the table of valid  ***/
  1973. /*** types:             ***/
  1974. /***      1-use anywhere     ***/
  1975. /***      2-must be exact match  ***/
  1976. /***      3-at beginning or all  ***/
  1977. /***      4-only in middle     ***/
  1978. /***      5-joins with same type ***/
  1979. /***      6-joins next-to,into,by***/
  1980. /***      7-not at beginning     ***/
  1981. /***      8-the word BE      ***/
  1982. /***      9-his,was,were,enough  ***/
  1983. /***     10-only at end      ***/
  1984. void do_letter()
  1985. {
  1986.   short i, j, k, l, matchend, wlength, wstart, casetype;
  1987.   BOOL matched;
  1988.   char *current_match, *next_match;
  1989.   lastmatch = count;
  1990.   wlength = (short) strlen(words);
  1991.   wstart = 0;
  1992.  
  1993.   join = group = FALSE;
  1994.   matched = FALSE;
  1995.   firstletter++;
  1996.   subvec[count] = point;    /* subvec indexes single letter in case
  1997.                  * there's no match */
  1998.   i = (short) (unsigned char) (words[count] - 64);
  1999.   /* we know i >=1 <=27 since word[count] is a letter */
  2000.   j = (short) (unsigned char) (words[count + 1] - 64);
  2001.   if (j < 0 || j > 27)
  2002.     j = 0;       /* not a letter */
  2003.   i = b.start2[i][j];
  2004. /*for example the word this i=20 j=8 and start2[i][j] points to where words
  2005. * starting with th start*/
  2006. /*if i or j is 0 we know there isn't a match*/
  2007.   if (i > 0 && xgrade >= GRADE2 && !xacronym)
  2008.     do
  2009.     {
  2010.       current_match = b.match[i];
  2011.       l = (short) strlen(current_match);
  2012.       matchend = (short) (count + l - 1);    /* points to last character
  2013.                          * of proposed match */
  2014.       if (strncmp(current_match, words + count, l))
  2015.     goto l10;  /* not a match */
  2016.  
  2017.       k = b.typex[i];
  2018.       if (firstletter > wstart && (k == 2 || k == 3 || k == 6 || k == 8 ||
  2019.                    k == 11))
  2020.     goto l10;
  2021.       if (firstletter == wstart && (k == 4 || k == 7))
  2022.     goto l10;
  2023.  
  2024.       j = b.typex[b.start1[(short) words[matchend + 1]]];    /* Next Letter */
  2025.       if (j > 0 && j < 19)
  2026.       {        /* not at end next char is a letter */
  2027.     if (k == 2 || k == 6 || k == 10)
  2028.       goto l10;
  2029.       }        /* not at end */
  2030.       else       /* Set end of Word if next char not Letter */
  2031.       {        /* at end */
  2032.     if (k == 4 || (k == 3 && strcmp(current_match, "IN") == 0))
  2033.       /* in [3,4] */
  2034.       goto l10;
  2035.     if (k == 11)
  2036.       goto l10;/* at beginning not all */
  2037.  
  2038.     if (k == 5 && firstletter == wstart && words[wstart] != '\\')
  2039.       group = TRUE;
  2040.  
  2041.     if (pjoin && k == 8)
  2042.       goto l10;
  2043.     if (k == 2 && strcmp(current_match, "US") == 0 &&
  2044.         capvec[firstletter] == UPPER && capvec[firstletter + 1] == UPPER)
  2045.       goto l10;
  2046.       }        /* at end */
  2047.  
  2048.       if ((k == 8) && (matchend == wlength - 1)
  2049.       && (wlength != l))
  2050.     goto l10;
  2051.  
  2052.       if ((k == 9) &&    /* was, his, etc. */
  2053.       ((l != wlength) ||
  2054.        pjoin))
  2055.     goto l10;
  2056.  
  2057.       if (k == 6)
  2058.       {
  2059.     if (matchend - wstart + 1 != wlength)
  2060.       goto l10;/* to Into by */
  2061.     join = TRUE;
  2062.       }
  2063.  
  2064.       casetype = capvec[count];
  2065.       if (casetype == LOWER)    /* lowercase */
  2066.     for (k = 0; current_match[k + 1]; k++)
  2067.       if (isupper(current_match[k + 1]))
  2068.         if (capvec[count + k + 1] != casetype)
  2069.           goto l10;
  2070.  
  2071.       subvec[count] = i;
  2072.       count = matchend;
  2073.       matched = TRUE;
  2074.  
  2075.   l10:if (!matched)
  2076.     i++;
  2077.       next_match = b.match[i];
  2078.     }           /* while */
  2079.     while ((!matched) && next_match[1] == current_match[1]);
  2080.   quoteopen = quoteclose = FALSE;
  2081. }           /* do_letter */
  2082.  
  2083. /***      Convert NumberS     ***/
  2084. /***           Type 19         ***/
  2085. void do_number()
  2086. {
  2087.   if (xgrade == GRADE0)
  2088.     return;       /* check for minus - make in (9) sign */
  2089.   firstletter = -1;
  2090.   subvec[count] = point;
  2091.   capvec[count] = NUMERIC;
  2092.   quoteopen = quoteclose = FALSE;
  2093. }           /* do_number */
  2094.  
  2095. /***  Convert THE PUNCTUATION     ***/
  2096. /***  Type 21 - Simple Replace     ***/
  2097. /***       22 - .         ***/
  2098. /***       24 - '                ***/
  2099. /***       25 - "                ***/
  2100. /***       27 - -         ***/
  2101. void do_punct()
  2102. {
  2103.   short i, k;
  2104.   BOOL matched;
  2105.   BOOL apostrophe;
  2106.  
  2107.   while (strncmp(b.match[point], words + count, strlen(b.match[point])))
  2108.     point++;
  2109.  
  2110.   if (count > 0)   /* Check for capital mark requirement */
  2111.     if (lastmatch >= 0)
  2112.     {
  2113.       k = b.typex[abs(subvec[lastmatch])];
  2114.       if (k == 6 || k == 8 || k == 9)
  2115.     subvec[lastmatch] = (short) -abs(subvec[lastmatch]);
  2116.     }
  2117.  
  2118.   matched = FALSE;
  2119.  
  2120.   join = group = pgroup = apostrophe = FALSE;
  2121.   k = b.typex[point];
  2122.  
  2123.   if (k == 24)
  2124.   {
  2125.     if ((isupper(words[count - 1]) || isdigit(words[count - 1])) &&
  2126.     (isupper(words[count + 1]) || isdigit(words[count + 1])))
  2127.       apostrophe = TRUE;
  2128.     if ((isupper(words[count - 1]) || isdigit(words[count - 1])) && quotecount == 0)
  2129.       apostrophe = TRUE;
  2130.     /*
  2131.      * if (count - 1 == (int) strlen(words) && (words[count - 1] == 'S' ||
  2132.      * words[count - 1] == 'N')) Maybe an apostrophe
  2133.      */
  2134.   }
  2135.   if (apostrophe == FALSE && (k == 24 || k == 25))
  2136.   {           /* Handle quotes */
  2137.     c = words[count - 1];
  2138.     if (quoteopen || ((count > 0) &&
  2139.         !(c == '(' || c == '-' || c == '"' || c == '\47' || c == '[') &&
  2140.               !quoteclose))
  2141.     {           /* Ending quote */
  2142.       if (quotecount & 1)
  2143.     subvec[count] = (short) (b.start1[34] + 1);
  2144.       else
  2145.     subvec[count] = (short) (b.start1[34] + 3);
  2146.       quotecount--;
  2147.       quoteopen = TRUE;
  2148.     }           /* ending quote */
  2149.     else
  2150.     {           /* Beginning quote */
  2151.       if (pjoin)
  2152.       {
  2153.     pjoin = FALSE;
  2154.     strcpy(bline, bline6);    /* reset for to into by */
  2155.       }
  2156.       quotecount++;
  2157.       if (quotecount & 1)
  2158.     subvec[count] = b.start1[34];
  2159.       else
  2160.     subvec[count] = (short) (b.start1[34] + 2);
  2161.       quoteclose = TRUE;
  2162.     }           /* beginning quote */
  2163.     return;
  2164.   }           /* handle quote */
  2165.  
  2166.   do
  2167.   {           /* Find replacement */
  2168.     i = (short) (count + strlen(b.match[point]) - 1);
  2169.     if (!strncmp(b.match[point], words + count, strlen(b.match[point])))
  2170.     {
  2171.       matched = TRUE;
  2172.       subvec[count] = point;
  2173.       count = i;
  2174.     }
  2175.     else
  2176.       point++;
  2177.   }
  2178.   while (!matched);
  2179.  
  2180.   if (b.typex[point] != 27)
  2181.     firstletter = -1;
  2182.   quoteopen = FALSE;
  2183.   quoteclose = FALSE;
  2184. }           /* do_punct */
  2185.  
  2186. /***   Build the Word From the     ***/
  2187. /***   Information kept in the     ***/
  2188. /***     contraction vector     ***/
  2189. void build_word()
  2190. {
  2191.   BOOL nolow, num = FALSE, allcaps = FALSE;
  2192.   short i, i1, j, k;
  2193.   bword[0] = bword6[0] = '\0';  /* start with no word */
  2194.   bword[MAXWORDLEN] = '\0';     /* tells if word gets too long */
  2195.  
  2196.   strcpy(oldword, words);
  2197.   for (i = 0; words[i]; i++)
  2198.   {
  2199.     if (bword[MAXWORDLEN])
  2200.       break;       /* quit before bword overflows */
  2201.     if (capvec[i] == NOTRANS)
  2202.     {           /* do not translate this char */
  2203.       j = (short) strlen(bword);
  2204.       bword[j] = (char) (words[i] & 127);
  2205.       bword[j + 1] = 0; /* only 1 character was added to bword */
  2206.     }           /* do not translate this char */
  2207.     else
  2208.     if (subvec[i])
  2209.     {
  2210.       if (subvec[i] < 0)
  2211.       {
  2212.     nolow = TRUE;
  2213.     subvec[i] = -subvec[i];
  2214.       }
  2215.       else
  2216.     nolow = FALSE;
  2217.  
  2218.       i1 = subvec[i];
  2219.       k = b.typex[i1];
  2220.       if ((!num) && ((k == 19)
  2221.              || ((k == 22) && (b.typex[subvec[i + 1]] == 19))))
  2222.       {
  2223.     strcat(bword, "#");
  2224.     num = TRUE;
  2225.     allcaps = FALSE;
  2226.     join = FALSE;
  2227.     group = FALSE;
  2228.     pgroup = FALSE;
  2229.       }
  2230.  
  2231.       if (k == 19 || k == 21 || k == 23 || k == 24 || k == 25 || k == 27 || k == 28)
  2232.     strcat(bword, b.replace[i1]);
  2233.  
  2234.       if (k == 22) /* period */
  2235.     if (b.typex[subvec[i + 1]] == 19)    /* numeric follows period */
  2236.       strcat(bword, ".");   /* decimal point */
  2237.     else
  2238.       strcat(bword, b.replace[i1]);
  2239.  
  2240.       if (k == 26)
  2241.     /* Percent */
  2242.     if (num)
  2243.     {
  2244.       j = strpos(bword, "#");
  2245.       if (!j)
  2246.         j++;
  2247.       insert(b.replace[i1], bword + (short) (j - 1));
  2248.     }
  2249.     else
  2250.       strcat(bword, b.replace[i1]);
  2251.  
  2252.       if ((k > 0 && k < 19) || k == 29)
  2253.       {
  2254.     if (num && strcmp(b.match[i1], "-"))
  2255.     {
  2256.       num = FALSE;
  2257.       if (words[i] == 'S' && words[i - 1] != '\47')
  2258.         strcat(bword, "'");
  2259.       if (capvec[i] == LOWER && (words[i] < 'K') &&
  2260.           (!isupper(words[i + 1])))
  2261.         strcat(bword, ";");
  2262.     }
  2263.     if (allcaps == FALSE && capvec[i] == UPPER)
  2264.     {
  2265.       pgroup = FALSE;
  2266.       j = (short) strlen(bword);
  2267.       strcat(bword, cap_single);
  2268.       if (capvec[i + 1] == UPPER)
  2269.       {
  2270.         strcpy(bword + j, cap_all);
  2271.         allcaps = TRUE;
  2272.       }
  2273.     }
  2274.     if (k == 6)
  2275.     {
  2276.       sprintf(bword6, "%s%s", bword, b.match[subvec[i]]);
  2277.       if (!strcmp(bword6, "INTO"))
  2278.         strcpy(bword6, "9TO");
  2279.     }
  2280.  
  2281.     if (nolow)
  2282.       strcat(bword, b.match[i1]);
  2283.     else
  2284.       strcat(bword, b.replace[i1]);
  2285.       }
  2286.     }
  2287.     if (!strcmp(words, "$"))
  2288.     {
  2289.       strcpy(bword, "4#");
  2290.       strcpy(bword6, bword);
  2291.     }
  2292.   }           /* i */
  2293. }           /* build_word */
  2294.  
  2295. void check_ham_call()
  2296. {
  2297.   short i = 0, l = (short) strlen(words), l1;
  2298.   if (l > 6)
  2299.     return;
  2300.   strcpy(temp, words);
  2301.   strupr(temp);
  2302.   if (strcmp(temp, words))
  2303.     return;       /* not uppercase */
  2304.   while (call_prefix[i])
  2305.   {
  2306.     l1 = (short) strlen(call_prefix[i]);
  2307.     if (!strncmp(temp, call_prefix[i], l1))
  2308.     {           /* match */
  2309.       if (!isdigit(temp[l1]))
  2310.     return;
  2311.       xacronym = TRUE;
  2312.       strlwr(words + l1 + 1);
  2313.       break;
  2314.     }           /* match */
  2315.     i++;
  2316.   }           /* while */
  2317. }           /* check_ham_call */
  2318.  
  2319. void trans_word()
  2320. {
  2321.   short k;
  2322.   quoteopen = quoteclose = FALSE;
  2323.   lastmatch = 0;
  2324.   firstletter = count = -1;
  2325.   do
  2326.   {
  2327.     count++;
  2328.     if (capvec[count] != NOTRANS)
  2329.     {           /* not | */
  2330.       chardec = (short) (unsigned char) words[count];
  2331.       point = b.start1[chardec];    /* = first table entry for this
  2332.                      * character */
  2333.       k = b.typex[point];
  2334.       if (!k)
  2335.     continue;  /* character not in table, not translated */
  2336.       if (k <= 11)
  2337.     do_letter();
  2338.       else
  2339.       {        /* not a letter */
  2340.     if (k == 19)
  2341.       do_number();
  2342.     else
  2343.       do_punct();
  2344.       }        /* not letter */
  2345.     }           /* not | */
  2346.   }
  2347.   while (words[count + 1]);
  2348. }           /* trans_word */
  2349.  
  2350. BOOL store_next_token()
  2351. {           /* removes next token from temp storing it in token[]
  2352.             * increment token_count */
  2353.   short retval = FALSE;
  2354.   char delim = ' ';
  2355.   char *cptr;
  2356.   while (temp[0] == ' ')
  2357.     strcpy(temp, temp + 1);    /* remove leading spaces */
  2358.   if (temp[0] == (char) 39 || temp[0] == (char) 34)
  2359.   {           /* ' or " */
  2360.     delim = temp[0];
  2361.     strcpy(temp, temp + 1);    /* remove delim */
  2362.   }
  2363.   if (!temp[0])
  2364.     return (FALSE);/* empty line */
  2365.   if (token_count >= MAX_TOKENS)
  2366.     print_error("More than %d tokens on line %d\n", MAX_TOKENS,
  2367.         linecount);
  2368.  
  2369.   cptr = strchr(temp, delim);
  2370.   if (cptr == NULL)
  2371.   {           /* last token on line */
  2372.     strcpy(token[token_count], temp);
  2373.     temp[0] = 0;
  2374.   }           /* last token */
  2375.   else
  2376.   {           /* found matching delim */
  2377.     *cptr = 0;
  2378.     strcpy(token[token_count], temp);
  2379.     strcpy(temp, cptr + 1);
  2380.     retval = TRUE;
  2381.   }           /* found delim match */
  2382.   token_count++;
  2383.   return (retval);
  2384. }           /* store_next_token */
  2385.  
  2386. void pop_token(char *string)
  2387. {
  2388.   string[0] = 0;
  2389.   if (current_token >= token_count)
  2390.     return;       /* no more stored tokens */
  2391.   strcpy(string, token[current_token]);
  2392.   current_token++;
  2393. }           /* pop_token */
  2394.  
  2395. short check_token()
  2396. {
  2397.   int i;
  2398.   if (!field[0])
  2399.     token_char = 199;
  2400.   else
  2401.   {           /* not empty */
  2402.     if (atol(field) > 0)
  2403.       token_char = 888;
  2404.     else
  2405.     {           /* word */
  2406.       strupr(field);
  2407.       i = -1;
  2408.       do
  2409.       {
  2410.     i++;
  2411.     if (!strncmp(field, token_names[i], strlen(token_names[i])))
  2412.       break;
  2413.       }
  2414.       while (token_names[i] != NULL);
  2415.       if (token_vals[i] == 999)
  2416.     print_error("Unknown token %s in line %d\n", field, linecount);
  2417.       token_char = token_vals[i];
  2418.     }           /* word */
  2419.   }           /* not empty */
  2420.   return (token_char);
  2421. }           /* check_token */
  2422.  
  2423. void add_efl_data(char *string)
  2424. {
  2425.   if (appcount >= MAX_EFL_DATA)
  2426.     print_error("\007More than %d emf_data entries\n");
  2427.   if (strlen(string) > MAX_EFL_DATA_LEN)
  2428.     print_error("\007efl_string > %d characters in line %d\n",
  2429.         MAX_EFL_DATA_LEN, linecount);
  2430.   strcpy(efl_data[appcount], string);
  2431.   appcount++;
  2432. }           /* add_efl_data */
  2433.  
  2434. void store_commands()
  2435. {
  2436.   current_token = 0;    /* start from beginning of token list */
  2437.   pop_token(field);/* get first token */
  2438.   strupr(field);
  2439.   if (strcmp(field, "LINE"))
  2440.     print_error("Invalid first Operation - must be LINE in line %d\n",
  2441.         linecount);
  2442.  
  2443.   pop_token(field);
  2444.   if (check_token() != 888)
  2445.     print_error("No line numbers specified in line %d\n", linecount);
  2446.  
  2447.   l[lopcount].startline = (short) atoi(field);    /* starting line */
  2448.   l[lopcount].endline = l[lopcount].startline;    /* in case there isn't a
  2449.                          * second line number */
  2450.   l[lopcount].fopstart = (short) fopcount;    /* where commands start for
  2451.                          * this line */
  2452.   pop_token(field);
  2453.   if (check_token() == 888)
  2454.   {           /* ending line number specified */
  2455.     l[lopcount].endline = (short) atoi(field);
  2456.     if (l[lopcount].endline < l[lopcount].startline)
  2457.       print_error("Ending line less than starting line in line %d\n",
  2458.           linecount);
  2459.     pop_token(field);
  2460.   }           /* ending line number specified */
  2461.  
  2462.   while (check_token() < 100)
  2463.   {           /* delete skip center indent list text page */
  2464.     if (format_string[0] == '\0' && (token_char == 4 || token_char == 5))
  2465.       print_error("\007Cannot skip or center lines: formatting is disabled in line %d\n",
  2466.           linecount);
  2467.     f[fopcount].fop = token_char;
  2468.     pop_token(field);
  2469.     if (token_char == 80)
  2470.     {           /* page */
  2471.       f[fopcount].fstart = (short) atoi(field);
  2472.       pop_token(field);
  2473.     }           /* page */
  2474.     fopcount++;
  2475.   }           /* while */
  2476.  
  2477.   if (check_token() == 202)
  2478.   {           /* match */
  2479.     test_range("match");
  2480.     l[lopcount].lflag = TRUE;    /* match subcommand is active */
  2481.     f[fopcount].fop = 202;    /* match operation */
  2482.     add_efl_data(field);
  2483.     f[fopcount].fappo = appcount;    /* index to match data -1 */
  2484.     pop_token(field);
  2485.     if (check_token() == 1)    /* delete */
  2486.       f[fopcount].fop = 201;    /* delete if match */
  2487.     fopcount++;
  2488.   }           /* match */
  2489.  
  2490.   while (check_token() == 100)
  2491.   {           /* field */
  2492.     f[fopcount].fop = 100;    /* indicate a field operation */
  2493.     test_range("field");
  2494.     f[fopcount].fop = 0;
  2495.  
  2496.     if (check_token() > 100 && token_char < 199)
  2497.     {           /* state or omit token */
  2498.       f[fopcount].fop = token_char;
  2499.       pop_token(field);
  2500.     }           /* state or omit */
  2501.  
  2502.     if (check_token() == 199)
  2503.     {           /* append */
  2504.       pop_token(field);
  2505.       add_efl_data(field);
  2506.       f[fopcount].fappo = appcount;
  2507.       pop_token(field);
  2508.       if (!f[fopcount].fop)
  2509.     /* there was no previous state or omit */
  2510.     f[fopcount].fop = 199;    /* indicate append operation */
  2511.     }           /* append */
  2512.     if (f[fopcount].fop)
  2513.       fopcount++;  /* valid field op was found */
  2514.   }           /* while */
  2515.  
  2516.   if (token_char >= 301 && token_char <= 311)
  2517.   {           /* replace */
  2518.     pop_token(field);
  2519.     strupr(field); /* make case insensitive */
  2520.     add_efl_data(field);
  2521.     if (!field[0])
  2522.       print_error("\007No string to replace in line %d\n", linecount);
  2523.     f[fopcount].fappo = appcount;
  2524.     pop_token(field);
  2525.     add_efl_data(field);
  2526.     f[fopcount].fop = token_char;
  2527.     fopcount++;
  2528.   }           /* replace */
  2529.   l[lopcount].fopend = fopcount;
  2530.   lopcount++;
  2531. }           /* store_commands */
  2532.  
  2533. void test_range(char *string)
  2534. {           /* used in store_commands to test range of match or field
  2535.             * entry */
  2536.   int i, fieldpos = 160, op;
  2537.   pop_token(field);
  2538.   if (check_token() != 888)
  2539.   {           /* no number specified */
  2540.     print_error("\007No %s numbers specified in line %d\n", string, linecount);
  2541.   }           /* no number specified */
  2542.   f[fopcount].fstart = (short) (abs(atoi(field)) - 1);
  2543.   f[fopcount].flen = 1;
  2544.   pop_token(field);
  2545.   if (check_token() == 888)
  2546.   {           /* got a number */
  2547.     i = abs(atoi(field)) - 1;
  2548.     f[fopcount].flen = (short) (i - f[fopcount].fstart + 1);
  2549.     if (f[fopcount].flen < 1)
  2550.       print_error("\007Invalid %s range in line %d\n", string, linecount);
  2551.     pop_token(field);
  2552.   }           /* got number */
  2553.   if (f[fopcount].fstart + f[fopcount].flen > 160)
  2554.     print_error("\007%s specification > 160 in line %d\n", string, linecount);
  2555.   for (i = l[lopcount].fopstart; i <= fopcount; i++)
  2556.   {
  2557.     op = f[i].fop;
  2558.     if (op >= 100 && op < 200)
  2559.     {           /* field operation */
  2560.       if (f[i].fstart + f[i].flen - 1 >= fieldpos)
  2561.     print_error("\007Fields out of order in line %d\n", linecount);
  2562.       fieldpos = f[i].fstart;
  2563.     }           /* field operation */
  2564.   }           /* i */
  2565. }           /* test_range */
  2566.  
  2567. void load_template()
  2568. {
  2569.   lfile = fopen(efl_file, FOPEN_READ);
  2570.   if (lfile == NULL)
  2571.   {           /* not found */
  2572.     if (efl_mode & 1)
  2573.       return;       /* ignore error, translate without .efl file */
  2574.     print_error("\007External Format File %s not found ...\n", efl_file);
  2575.   }           /* not found */
  2576.  
  2577.   if (efl_mode & 4)
  2578.     fprintf(stderr, "External Format File %s\n", efl_file);
  2579.  
  2580.   linecount = lopcount = fopcount = appcount = 0;
  2581.   /* initialize structures */
  2582.   memset(f, 0, sizeof(foptype));
  2583.   memset(l, 0, sizeof(loptype));
  2584.   memset(efl_data, 0, sizeof(efl_data));
  2585.   while (fgets(temp, 100, lfile))
  2586.   {           /* while there are lines to read */
  2587.     temp[strlen(temp) - 1] = 0; /* get rid of lf */
  2588.     linecount++;
  2589.     if (temp[0] == ';' || temp[0] == '#')
  2590.       continue;    /* skip comment */
  2591.     token_count = 0;    /* tokens found on this line */
  2592.     while (store_next_token()); /* store tokens from entire line */
  2593.     if (token_count)
  2594.       store_commands(); /* tokens were found */
  2595.   }           /* while */
  2596.   if (lopcount)
  2597.   {
  2598.     lopactive = TRUE;
  2599.     if (efl_mode & 4)
  2600.       fprintf(stderr, "%d External Format lines were Processed\n", linecount);
  2601.   }
  2602.   else
  2603.     fprintf(stderr, "No external format lines were processed\n");
  2604.   fclose(lfile);
  2605. }           /* load_template */
  2606.  
  2607. void do_translate()
  2608. {
  2609.   short i;
  2610.  
  2611.   copies++;
  2612.   current_pass = 1;
  2613.   xformat_save = xformat;
  2614. get_next_pass:
  2615.   /* initialize variables before translation */
  2616.   memset(tabtable, 0, sizeof(tabtable));
  2617.   pgroup = pjoin = join = group = FALSE;
  2618.   xacronym = TRUE;
  2619.   xcenter = FALSE;
  2620.   blank_lines = 0;
  2621.   xtab = dobook = xdouble = xheading = xfooting = FALSE;
  2622.   makefoot = makehead = FALSE;
  2623.   pageset = FALSE;
  2624.   doroman = FALSE;
  2625.   pagenumlen = (short) (4 * (dopagenum == TRUE));
  2626.   disablecol = FALSE;
  2627.   fillit = FALSE;
  2628.   quotecount = 0;
  2629.   margin = 1;
  2630.   setmargin = 1;
  2631.   oldmargin = 1;
  2632.   tabmargin = FALSE;
  2633.   bpageb = 0;
  2634.   bpagec = 0;
  2635.   blinec = 0;
  2636.   actualpage = 0;
  2637.   lineinct = 0;
  2638.   inpglen = 0;
  2639.   it_flag = 0;
  2640.   total_words = total_cells = 0l, total_rejoins = 0l;
  2641.   memset(total_dots, 0, 28);
  2642.   field[0] = 0;
  2643.   addchar[0] = 0;
  2644.   curmax = maxline;
  2645.   linelength = maxline + 1 - margin;
  2646.   plinein = &linein[0];
  2647.   fill_length = 6;
  2648.   done = FALSE;
  2649.   top_of_form();
  2650.   bline[0] = '\0';
  2651.   if (!total_words)
  2652.   {
  2653.     if (print_file)
  2654.     {           /* file */
  2655.       strcpy(bline, inf_name + (print_file > 1) * inf_path_len);
  2656.       if (!print_date)
  2657.     bline[curmax - 4] = '\0';
  2658.       else
  2659.     bline[20 + 12 * (print_date > 1)] = '\0';       /* leave room for date */
  2660. #ifdef DOS
  2661.       strlwr(bline);
  2662. #endif
  2663.     }           /* file */
  2664.     if (print_date)
  2665.     {           /* date */
  2666.       if (bline[0])
  2667.     strcat(bline, " ");
  2668.       if (print_date > 1)
  2669.     date_string[12] = '\0';
  2670.       strcat(bline, date_string);
  2671.       date_string[12] = ' ';
  2672.     }           /* date */
  2673.     if (bline[0] && pagestart == 1)
  2674.       bpurge();
  2675.     bline[0] = 0;
  2676.   }
  2677.  
  2678.   if (inf_des)
  2679.     lseek(inf_des, 0l, 0);    /* start from beginning for each copy */
  2680.   bytes_in_buf = 0;/* no bytes in iobuf */
  2681.   if (rejoin & 6)
  2682.     if (hyp_ptr)
  2683.       fseek(hyp_ptr, 0l, 0);    /* only if file is open */
  2684.   do
  2685.   {
  2686.     get_word();
  2687.     if (plinein >= eolptr)
  2688.     {           /* last word on line */
  2689.       if (got_toc_page == 0 && (words[0] == '$' || words[0] == '`'))
  2690.       {        /* last toc word */
  2691.     if (words[0] == '`')
  2692.       strcpy(words, words + 1);
  2693.     last_toc_word = TRUE;
  2694.       }        /* last toc word */
  2695.       if (rejoin)
  2696.       {
  2697.     i = (short) strlen(words);
  2698.     if (i > 1 && words[i - 1] == '-' && ISalpha(words[i - 2]) &&
  2699.         strpbrk(words, "*+/%()") == NULL && strchr(words, '-') == words + i - 1)
  2700.     {       /* proposed hyphenated word */
  2701.       strcpy(oldword, words);
  2702.       get_word();
  2703.       if (ISalpha(words[0]) && ISalpha(words[1]) &&
  2704.           strchr(words, '-') == NULL)
  2705.       {       /* join */
  2706.         if (rejoin & 6)
  2707.         {       /* output to file or stderr */
  2708.           sprintf(temp, "%s %s line %ld page %d\n", oldword, words,
  2709.               total_lines, bpagec);
  2710.           if (rejoin & 4)
  2711.           {    /* read or write hyphen file */
  2712.         if (!read_hyphen_file)
  2713.         {  /* write */
  2714.           if (!total_rejoins)
  2715.           {
  2716.             hyp_ptr = fopen(hyphen_file, "w");
  2717.             if (!hyp_ptr)
  2718.               print_error("\007Unable to open %s\n", hyphen_file);
  2719.           }
  2720.           fprintf(hyp_ptr, temp);
  2721.         }  /* write */
  2722.         else
  2723.         {  /* read */
  2724.           fgets(field, 80, hyp_ptr);
  2725.           if (strcmp(temp, field))
  2726.             goto no_rejoin;
  2727.         }  /* read */
  2728.           }    /* read or write hyphen file */
  2729.           if (rejoin & 2)
  2730.         fprintf(stderr, temp);
  2731.         }       /* output to file or stderr */
  2732.  
  2733.         strncpy(oldword + i - 1, words, sizeof(words) - i);
  2734.         strcpy(words, oldword);
  2735.         total_rejoins++;
  2736.       }       /* join */
  2737.       else
  2738.       {       /* doesn't begin with a letter so don't join */
  2739.     no_rejoin:
  2740.         plinein = &linein[0];    /* unget the word */
  2741.         strcpy(words, oldword);
  2742.       }       /* word doesn't begin with letter so don't join */
  2743.     }       /* proposed hyphenated word */
  2744.       }
  2745.     }           /* last word on line */
  2746.     if (words[0])
  2747.     {           /* word not empty */
  2748.       total_words++;
  2749.       if (xgrade)
  2750.       {        /* grade 1-3 */
  2751.     check_ham_call();
  2752.     set_vect();
  2753.     trans_word();
  2754.     build_word();
  2755.       }        /* grade 1-3 */
  2756.       else
  2757.       {        /* computer braille */
  2758.     if (!grade_mod)
  2759.     {       /* grade 0 no translation */
  2760.       strcpy(bword, words);
  2761.       strcpy(bword6, words);
  2762.     }       /* grade 0 no translation */
  2763.     else
  2764.       add_case();
  2765.       }        /* computer braille */
  2766.       if (plinein >= eolptr && line_end[0])
  2767.     strcat(bword, line_end);
  2768.       build_line();
  2769.     }           /* word not empty */
  2770.     if (stdin_tty)
  2771.       check_keyboard(1);
  2772.   }           /* while */
  2773.   while (!done);
  2774.   if (inf_des_save != inf_des)
  2775.     close(inf_des);/* close linked file */
  2776.   inf_des = inf_des_save;
  2777.   if (ab_flag)
  2778.     return;
  2779.   if (find_toc_pages && current_pass < 2)
  2780.   {
  2781.     /* look for toc entry without corresponding title */
  2782.     for (i = 0; i < MAX_TOC_ENTRY; i++)
  2783.       if (toc_pages[i] < 0)
  2784.     print_error("\007Cannot find matching ~F%d\n", i + 1);
  2785.     if (bpagec < pagestart_save)
  2786.       goto delete;
  2787.     current_pass++;
  2788.     pagestart = pagestart_save;
  2789.     pageend = pageend_save;
  2790.     xformat = xformat_save;
  2791.     goto get_next_pass;
  2792.   }
  2793.   if (bpagec < pagestart)
  2794.   {
  2795.     if (strcmp(outf_name, prn))
  2796.     {
  2797.   delete:close(outf_des);
  2798.       unlink(outf_name);
  2799.     }
  2800.     return;
  2801.   }
  2802.   if (strcmp(bline, indent))
  2803.   {
  2804.     bpurge();
  2805.     if (xfooting && blinec > 0)
  2806.     {           /* put footing on last page */
  2807.       for (i = (short) (blinec + 2); i <= linesperpage; i++)
  2808.     if (bpagec > pagestart)
  2809.       write_string(" ", 1);
  2810.       if (bpagec > pagestart)
  2811.     write_string(fline, 1);
  2812.       blinec = linesperpage;
  2813.     }           /* put footing on last page */
  2814.   }
  2815.  
  2816.   if (blinec > 0)
  2817.   {           /* advance to top of next page */
  2818.     advance_page();
  2819.     /* we are at the top of bpagec+1 */
  2820.     actualpage++;
  2821.   }           /* advance to top of next page */
  2822.  
  2823.   if (interpoint)
  2824.   {
  2825.     if (!(actualpage & 1))
  2826.     {           /* skip interpoint even page */
  2827.       blinec = 0;  /* skip whole page */
  2828.       advance_page();
  2829.     }           /* skip interpoint even page */
  2830.     if (interpoint > 1)
  2831.       for (i = 0; i < 2; i++)
  2832.     advance_page();
  2833.   }           /* interpoint */
  2834. }           /* do_translate */
  2835.  
  2836. void write_stat_file()
  2837. {
  2838.   int i;
  2839.   if (bpagec < pagestart)
  2840.     return;       /* no output */
  2841.   if (stat_file[0] && intext == NULL)
  2842.     intext = fopen(stat_file, "a");
  2843.   if (intext != NULL)
  2844.   {           /* open */
  2845.     time(&time2);
  2846.     time2 -= time1;
  2847.     fprintf(intext, "%s\n", date_string);
  2848.     if (inf_name[0])
  2849.       fprintf(intext, "Input File: %s\n", inf_name);
  2850.     fprintf(intext, "Translation time: %ld minutes %ld seconds\n", time2 / 60l, time2 % 60l);
  2851.     fprintf(intext, "LinesPerPage: %d\n", linesperpage);
  2852.     fprintf(intext, "LineLength: %d\n", curmax);
  2853.     fprintf(intext, "Words: %ld\n", total_words);
  2854.     fprintf(intext, "Pages: %d\n", bpagec);
  2855.     fprintf(intext, "Words per Page: %ld\n", total_words / (long) bpagec);
  2856.     if (time2)
  2857.     {
  2858.       fprintf(intext, "Words per Second: %ld\n", total_words / time2);
  2859.       fprintf(intext, "Characters per Second: %ld\n", total_cells / time2);
  2860.     }
  2861.     fprintf(intext, "Estimated Embossing Time: %ld Minutes\n", emboss_time);
  2862.     if (total_rejoins)
  2863.       fprintf(intext, "Rejoined words: %ld\n", total_rejoins);
  2864.     fprintf(intext, "Total Cells: %ld\n", total_cells);
  2865.     total = 0l;
  2866.     for (i = 0; i <= 5; i++)
  2867.       total += total_dots[i];
  2868.     fprintf(intext, "Total Dots: %ld\n", total);
  2869.     if (total)
  2870.       for (i = 0; i <= 5; i++)
  2871.     fprintf(intext, "Dot%d: %6ld = %ld%%\n", i + 1, total_dots[i],
  2872.         total_dots[i] * 100l / total);
  2873.     if (total_dots[6])
  2874.       fprintf(intext, "Dot 7: %6ld\n", total_dots[6]);
  2875.     if (in_length)
  2876.       fprintf(intext, "Input file length: %ld\n", in_length);
  2877.     fprintf(intext, "Output file length: %ld\n", out_length);
  2878.     if (!ab_flag)
  2879.       if (in_length != 0l && ab_flag == 0)
  2880.     fprintf(intext, "Output is %ld%% of input\n", 100l * out_length / in_length);
  2881.     if (ab_flag)
  2882.       fprintf(intext, "Aborted\n");
  2883.     fprintf(intext, "Entries in table: %d\n\n", table_entries);
  2884.   }           /* open */
  2885. }           /* write_stat_file */
  2886.  
  2887. void advance_page()
  2888. {
  2889.   short i;
  2890.   if (lineskips < 99)
  2891.     for (i = blinec; i < linesperpage + lineskips; i++)
  2892.     {
  2893.       write_string(" ", 1);     /* do it with linefeeds */
  2894.     }
  2895.   if (lineskips == 99)
  2896.     write_char(12);/* do it with a formfeed */
  2897.   if (lineskips == 999)
  2898.     write_char(11);/* vertical tab no lf */
  2899.   if (lineskips == 9999)
  2900.   {
  2901.     write_string("\14", 0);     /* formfeed with linefeed */
  2902.     printf("\nTo Continue, Press Return\n");
  2903.     getch();
  2904.   }
  2905. }           /* advance_page */
  2906.  
  2907. void load_tables()
  2908. {
  2909.   short j, k, error = 0, current_line = 0;
  2910.   char match[20], prev_match[20];
  2911.   short lenmat, lenrep, typex;
  2912.   FILE *btable;
  2913.   char *ver_bar, *c;
  2914.   if (!reload_table)
  2915.     return;
  2916.   reload_table = FALSE;
  2917.   sprintf(temp, "%s%s", transpath, table_file);
  2918.   if ((btable = fopen(temp, FOPEN_READ)) == NULL)
  2919.     print_error("\7Cannot find %s\n", temp);
  2920.   table_entries = 0;
  2921.   memset(&b, 0, sizeof(tablet));    /* fill in structure with zeros */
  2922.   prev_match[0] = '\0'; /* forces mismatch between match and prev_match on
  2923.              * first line */
  2924.   while (fgets(temp, 80, btable))
  2925.   {           /* while there are lines to read */
  2926.     current_line++;
  2927.     trim(temp);
  2928.     /* skip blank lines and comments starting with ; or # */
  2929.     if (temp[0] < ' ' || temp[0] == ';' || temp[0] == '#')
  2930.       continue;
  2931.     strupr(temp);
  2932.     if (isalpha(temp[0]) && temp[2] == '=')
  2933.     {
  2934.       process_options(temp);
  2935.       continue;
  2936.     }
  2937.     if ((ver_bar = strchr(temp, '|')) == NULL)
  2938.     {           /* error */
  2939.   no_ver_bar:error++;
  2940.       fprintf(stderr, "\7Improper placement of | error in line %d\n",
  2941.           current_line);
  2942.       break;
  2943.     }           /* error */
  2944.     *ver_bar = (char) 0;
  2945.     typex = (short) atoi(temp);
  2946.     *ver_bar = '|';/* restore temp */
  2947.     c = ver_bar + 1;    /* beginning of match */
  2948.     if ((ver_bar = strchr(ver_bar + 1, '|')) == NULL)
  2949.       goto no_ver_bar;
  2950.     *ver_bar = (char) 0;
  2951.     lenmat = (short) strlen(c);
  2952.     if (lenmat > MAX_MATCH)
  2953.     {           /* too long */
  2954.       fprintf(stderr, "\7Error - match too long in line %d\n%s\n", current_line,
  2955.           temp);
  2956.       error++;
  2957.       break;
  2958.     }           /* too long */
  2959.     if (*c >= '0' && *c <= '9' && c[1] >= '0' && c[1] <= '9')
  2960.     {
  2961.       match[0] = (char) atoi(c);
  2962.       match[1] = '\0';
  2963.       lenmat = 1;
  2964.     }
  2965.     else
  2966.       strcpy(match, c);
  2967.     if (*c < '\0' && (typex < 28 || typex > 29))
  2968.       goto bad_type;
  2969.     *ver_bar = '|';/* restore temp */
  2970.     c = strchr(ver_bar, ' ');
  2971.     if (c)
  2972.       *c = '\0';   /* remove extra comment words after table entry */
  2973.     lenrep = (short) strlen(ver_bar + 1);
  2974.     if (lenrep > MAX_REP)
  2975.     {           /* replace too long */
  2976.       fprintf(stderr, "\7Error - Replace too long in line %d\n%s\n", current_line,
  2977.           temp);
  2978.       error++;
  2979.       break;
  2980.     }           /* replace too long */
  2981.     if (table_entries >= MAXTAB)
  2982.     {           /* too many entries */
  2983.       fprintf(stderr, "\7More than %d entries in table not allowed\n", MAXTAB);
  2984.       fprintf(stderr, "Remaining entries will be ignored.\n");
  2985.       break;       /* quit reading the table not fatal */
  2986.     }           /* too many entries */
  2987.     if (typex <= -32 || typex >= 64)
  2988.     {           /* bad type */
  2989.   bad_type:fprintf(stderr, "\7Invalid type %d in line %d\n", typex, current_line);
  2990.       error++;
  2991.       break;
  2992.     }           /* type error */
  2993.     if (xgrade == GRADE3)
  2994.     {           /* grade 3 */
  2995.       if (grade_mod == 0 && typex < 0)
  2996.     continue;  /* skip unwanted g2 entry */
  2997.       typex = (short) abs(typex);
  2998.       if (typex > 32 && grade_mod > 0)
  2999.       {        /* grade_mod nonstandard grade 3 */
  3000.     /* skip entries other than dot 4 5 45 and 456 contractions */
  3001.     if (!strpbrk(ver_bar + 1, "@\042^_"))
  3002.       continue;
  3003.     temp[1] = '\0';
  3004.     temp[0] = ver_bar[2];
  3005.     if ((grade_mod & 1) && (isupper(temp[0])))
  3006.       goto keep_entry;
  3007.     if ((grade_mod & 2) && (isdigit(temp[0])))
  3008.       goto keep_entry;
  3009.     if ((grade_mod & 4) && (strpbrk(temp, single_dot) == NULL)
  3010.         && (grade_mod & 3) == 0)
  3011.       goto keep_entry;
  3012.     if ((grade_mod & 8) && strpbrk(temp, single_dot))
  3013.       goto keep_entry;
  3014.     continue;
  3015.       }        /* grade_mod */
  3016.  
  3017.   keep_entry:
  3018.       typex &= 31;
  3019.     }           /* grade 3 */
  3020.     else
  3021.     if (typex > 32)
  3022.       continue;    /* skip g3 entry */
  3023.     if (typex > 29 || (typex > 11 && typex < 19))
  3024.       goto bad_type;
  3025.     table_entries++;    /* we found a valid line, store results */
  3026.     b.typex[table_entries] = (short) abs(typex);
  3027.     strcpy(b.match[table_entries], match);
  3028.     strcpy(b.replace[table_entries], ver_bar + 1);
  3029.     if (table_entries > 1)    /* store previous match in prev_match */
  3030.       strcpy(prev_match, b.match[table_entries - 1]);
  3031.     j = (short) (match[0] - '@');
  3032.     if (j < 0 || j > 26)
  3033.       j = 0;
  3034.     if (strcmp(prev_match, match) >= 0)
  3035.       if (strncmp(prev_match, match, lenmat))
  3036.       {
  3037.     fprintf(stderr, "\007Sorting error in line %d\n", current_line);
  3038.     error++;
  3039.     break;
  3040.       }
  3041.     if (match[0] != prev_match[0])
  3042.     {           /* first characters differ */
  3043.       if (lenmat != 1 && isupper(match[0]))
  3044.       {        /* error */
  3045.     fprintf(stderr, "\007Match should be a single character in line %d %s\n"
  3046.         ,current_line, temp);
  3047.     error++;
  3048.     break;
  3049.       }        /* error */
  3050.       b.start1[(short) (unsigned char) (match[0])] = table_entries;
  3051.       b.start2[j][0] = table_entries;
  3052.     }           /* first characters differ */
  3053.     else
  3054.     if ((match[1] != prev_match[1]))
  3055.     {           /* second element of match and previous match differ */
  3056.       k = (short) (match[1] - '@');
  3057.       if (k < 0 || k > 26)
  3058.     k = 0;
  3059.       b.start2[j][k] = table_entries;
  3060.     }           /* second elements differ */
  3061.   }           /* while */
  3062.   fclose(btable);
  3063.   if (error)
  3064.     print_error("Correct error in %s and restart program.\n", table_file);
  3065. }           /* load_tables */
  3066.  
  3067. void get_config()
  3068. {
  3069.   short i;
  3070.   char *c, *cptr;
  3071.   if (!total_files)
  3072.   {
  3073.     if (paramcount > 0)
  3074.     {
  3075.       strcpy(temp, paramstr[1]);
  3076.       strupr(temp);
  3077.       if (!strncmp(temp, "CF=", 3))
  3078.       {        /* new config file */
  3079.     strcpy(config_file, paramstr[1] + 3);
  3080.     start_arg++;
  3081.       }        /* new config file */
  3082.     }
  3083.     for (i = 0; i < 3; i++)
  3084.     {           /* try current directory first, then use nfbtrans
  3085.             * environment variable then program path */
  3086.       switch (i)
  3087.       {
  3088.       case 1:      /* check environment */
  3089.     c = (char *) getenv("NFBTRANS");
  3090.     if (c)
  3091.     {       /* nfbtrans defined */
  3092.       strcpy(transpath, c);
  3093.       if (transpath[strlen(transpath) - 1] != '\\')
  3094.         strcat(transpath, "\\");
  3095.     }       /* nfbtrans defined */
  3096.     break;
  3097.       case 2:      /* program path */
  3098. #ifdef unix
  3099.     break;       /* path not in argv[0] */
  3100. #endif
  3101.     strcpy(transpath, paramstr[0]);
  3102.     c = strrchr(transpath, '\\');
  3103.     if (c)
  3104.       c[1] = 0;/* we have program path */
  3105.       }        /* switch */
  3106.       sprintf(temp, "%s%s", transpath, config_file);
  3107.       if ((conf_ptr = fopen(temp, FOPEN_READ)) == NULL)
  3108.     continue;
  3109.       break;       /* file is open */
  3110.     }           /* i */
  3111.     if (!conf_ptr)
  3112.       print_error("\007%s not found\n", config_file);
  3113.   }
  3114.   else
  3115.     fseek(conf_ptr, 0l, 0);
  3116.   while (fgets(temp, 100, conf_ptr))
  3117.   {           /* while there are lines to read */
  3118.     if (strlen(temp) > 95)
  3119.       print_error("\7Line too long in %s%s\n", transpath,
  3120.           config_file);
  3121.  
  3122.     strupr(temp);
  3123.     trim(temp);
  3124.     if (temp[0] == '\n' || temp[0] == ';' || temp[0] == '#')
  3125.       continue;    /* skip */
  3126.     if ((cptr = strchr(temp, ' ')) != NULL)
  3127.       *cptr = 0;   /* allows comments starting with second word */
  3128.     process_options(temp);
  3129.   }           /* while */
  3130.   if (!total_files)
  3131.     for (i = start_arg; i <= paramcount; i++)
  3132.     {
  3133.       if (paramstr[i][2] == '=')
  3134.       {        /* xx= */
  3135.     strupr(paramstr[i]);
  3136.     process_options(paramstr[i]);
  3137.       }        /* xx= */
  3138.       else
  3139.       {        /* not xx= */
  3140.     usr_default = TRUE;
  3141.     /*
  3142.      * if input is from keyboard assume arguments are input files. Else
  3143.      * ignore
  3144.      */
  3145.     if (stdin_tty)
  3146.       input_file_arg = i;
  3147.     break;
  3148.       }        /* not xx= */
  3149.     }           /* i */
  3150.   if (!stdin_tty)
  3151.   {
  3152.     inf_des = 0;
  3153.     usr_default = TRUE;
  3154.   }
  3155.   if (!stdout_tty)
  3156.   {
  3157.     outf_des = 1;
  3158. #ifdef DOS
  3159.     setmode(1, O_BINARY);
  3160. #endif
  3161.     trans_mode = 11;
  3162.   }
  3163.   if (usr_default)
  3164.   {
  3165.     display_source = FALSE;
  3166.     lastcopy = 1;
  3167.     if (pagestart <= 0)
  3168.       pagestart = 1;
  3169.     if (pageend < pagestart)
  3170.       pageend = 9999;    /* print entire document */
  3171.     if (leftmargin < 1)
  3172.       leftmargin = 1;
  3173.     if (maxline <= 1)
  3174.       maxline = 40;
  3175.     if (linesperpage <= 0)
  3176.       linesperpage = 25;
  3177.     if (lineskips < 0)
  3178.       lineskips = 99;
  3179.     if (trans_mode <= 0)
  3180.       trans_mode = 21;
  3181.     display_braille = 0;
  3182.   }
  3183. }           /* get_config */
  3184.  
  3185. void process_options(char *string)
  3186. {
  3187.   short j, x;
  3188.   char *cptr = string + 3, *vptr;
  3189.   for (j = 0; options[j] != NULL; j++)
  3190.   {
  3191.     if (!strncmp(string, options[j], 2))
  3192.     {           /* option matched */
  3193.       if (*cptr <= ' ')
  3194.     j = -1;    /* error since nothing follows xx= */
  3195.       if (cptr[0] == '\042')
  3196.       {        /* quoted string */
  3197.     strcpy(cptr, cptr + 1);
  3198.     vptr = strchr(cptr, '\042');
  3199.     if (!vptr)
  3200.       print_error("\007Unmatched quoted string in line %ld",
  3201.               total_lines);
  3202.     vptr[0] = 0;
  3203.       }        /* quoted string */
  3204.       x = (short) atoi(cptr);    /* saves multiple calls to atoi */
  3205.       switch (j)
  3206.       {
  3207.       case 0:      /* ca */
  3208.     vptr = strchr(cptr, '|');
  3209.     if (!vptr)
  3210.       goto no_ver_bar;
  3211.     *vptr = '\0';
  3212.     strncpy(cap_single, cptr, sizeof(cap_single));
  3213.     strncpy(cap_all, vptr + 1, sizeof(cap_all));
  3214.     break;
  3215.       case 1:      /* cl */
  3216.     center_length = x;
  3217.     break;
  3218.       case 2:      /* co */
  3219.     lastcopy = x;
  3220.     break;
  3221.       case 3:      /* cs */
  3222.     charspersec = x;
  3223.     break;
  3224.       case 4:      /* db */
  3225.     display_braille = x;
  3226.     break;
  3227.       case 5:      /* de */
  3228.     emboss_delay = x;
  3229.     break;
  3230.       case 6:      /* ds */
  3231.     display_source = x;
  3232.     break;
  3233.       case 7:      /* ef */
  3234.     efl_mode = x;
  3235.     break;
  3236.       case 8:      /* et */
  3237.     expand_tab = x;
  3238.     break;
  3239.       case 9:      /* ex */
  3240.     if (total_lines)
  3241.       print_error("\007ex option allowed only in nfbtrans.cnf or on command line\n");
  3242.     if (total_files)
  3243.       break;   /* only get once from nfbtrans.cnf */
  3244.     for (;;)
  3245.     {
  3246.       if (prog_extension.total >= MAX_EXTENSIONS)
  3247.         print_error(
  3248.           "\007Too many extensions.  only the first %d can be stored\n",
  3249.             MAX_EXTENSIONS);
  3250.       vptr = strchr(cptr, '=');
  3251.       if (vptr == NULL)
  3252.         break; /* no more extensions */
  3253.       *vptr = 0;    /* terminate extension */
  3254.       if (strlen(cptr) > 8)
  3255.         goto invalid;
  3256.       strcpy(prog_extension.prog_ext[prog_extension.total].ext, cptr);
  3257.       *vptr = ' ';  /* in case theres an error */
  3258.       x = (short) (vptr[1] - 48);
  3259.       if (vptr[1] == '-')
  3260.         vptr[1] = '0';
  3261.       if (x > 9)
  3262.         x -= 7;
  3263.       if (x > 14 || isxdigit(vptr[1]) == 0)
  3264.         goto invalid;
  3265.       prog_extension.prog_ext[prog_extension.total].init_val = x;
  3266.       cptr = vptr + 2;
  3267.       prog_extension.total++;
  3268.     }
  3269.     break;
  3270.       case 10:      /* fp */
  3271.     first_page = x;
  3272.     break;
  3273.       case 11:      /* fs */
  3274.     copy_string(format_string, cptr, 3);
  3275.     break;
  3276.       case 12:      /* gd */
  3277.     guide_dots = x;
  3278.     break;
  3279.       case 13:      /* gm */
  3280.     graphics_mode = x;
  3281.     break;
  3282.       case 14:      /* he */
  3283.     strncpy(hyphen_extension, cptr, 4);
  3284.     break;
  3285.       case 15:      /* hk */
  3286.     hot_key = x;
  3287.     break;
  3288.       case 16:      /* i0 */
  3289.       case 17:      /* i1 */
  3290.       case 18:      /* i2 */
  3291.       case 19:      /* i3 */
  3292.       case 20:      /* i4 */
  3293.       case 21:      /* i5 */
  3294.       case 22:      /* i6 */
  3295.       case 23:      /* i7 */
  3296.       case 24:      /* i8 */
  3297.       case 25:      /* i9 */
  3298.       case 26:      /* ia */
  3299.       case 27:      /* ib */
  3300.       case 28:      /* ic */
  3301.       case 29:      /* id */
  3302.       case 30:      /* ie */
  3303.     if (total_lines)
  3304.       print_error("\007Initialization option not allowed in file\n");
  3305.     if (total_files)
  3306.       break;
  3307.     x = (short) (string[1] - 48);
  3308.     if (x > 9)
  3309.       x -= 7;
  3310.     vptr = strchr(cptr, '|');
  3311.     if (!vptr)
  3312.       no_ver_bar:print_error("\007Missing | in %s\n", string);
  3313.     *vptr = 0;
  3314.     if (strlen(cptr) > MAX_INIT)
  3315.     {
  3316.       init_err:
  3317.       print_error("\007Initialization string > %d characters %s\n",
  3318.               MAX_INIT, string);
  3319.     }
  3320.     copy_string(init[x].pre_init, cptr, MAX_INIT);
  3321.     cptr = vptr + 1;
  3322.     vptr = strchr(cptr, '|');
  3323.     if (!vptr)
  3324.       goto no_ver_bar;
  3325.     *vptr = 0;
  3326.     if (strlen(cptr) > MAX_INIT)
  3327.       goto init_err;
  3328.     copy_string(init[x].post_init, cptr, MAX_INIT);
  3329.     copy_string(init[x].format, vptr + 1, 3);
  3330.     break;
  3331.       case 31:      /* interpoint */
  3332.     interpoint = x;
  3333.     break;
  3334.       case 32:      /* it */
  3335.     italics = *cptr;
  3336.     break;
  3337.       case 33:      /* kc */
  3338.     keep_control = x;
  3339.     break;
  3340.       case 34:      /* l0 */
  3341.     strncpy(l0, cptr, sizeof(l0));
  3342.     break;
  3343.       case 35:      /* l1 */
  3344.     strncpy(l1, cptr, sizeof(l1));
  3345.     break;
  3346.       case 36:      /* le */
  3347.     if (lopactive)
  3348.       print_error("\7EFL file already loaded\n");
  3349.     strncpy(efl_file, cptr, sizeof(efl_file));
  3350.     load_template();
  3351.     break;
  3352.       case 37:      /* lf */
  3353.     if (total_lines == 0 || stdin_tty == 0)
  3354.       print_error(
  3355.         "lf option not allowed until translation is in progress\n");
  3356.     if (inf_des_save != inf_des)
  3357.       close(inf_des);
  3358.     strcpy(inf_name + inf_path_len, cptr);
  3359.     inf_des = open_input_file();
  3360.     bytes_in_buf = 0;
  3361.     linein[0] = 0;
  3362.     break;
  3363.       case 38:      /* li */
  3364.     strncpy(line_end, cptr, sizeof(line_end));
  3365.     break;
  3366.       case 39:      /* lm */
  3367.     leftmargin = x;
  3368.     break;
  3369.       case 40:      /* ls */
  3370.     lineskips = x;
  3371.     break;
  3372.       case 41:      /* mm */
  3373.     max_menu = x != 3 ? (short) 2 : (short) 3;
  3374.     break;
  3375.       case 42:      /* nc */
  3376.     no_copyright = x;
  3377.     break;
  3378.       case 43:      /* ow */
  3379.     over_write = x;
  3380.     break;
  3381.       case 44:      /* pa */
  3382.     pause_time = x;
  3383.     spool = 0;
  3384.     display_braille = display_source = FALSE;
  3385.     break;
  3386.       case 45:      /* pd */
  3387.     print_date = x;
  3388.     break;
  3389.       case 46:      /* pe */
  3390.     pageend = x;
  3391.     break;
  3392.       case 47:      /* pf */
  3393.     print_file = x;
  3394.     break;
  3395.       case 48:      /* pl */
  3396.     linesperpage = x;
  3397.     break;
  3398.       case 49:      /* pn */
  3399.     strncpy(prn, cptr, sizeof(prn));
  3400.     break;
  3401.       case 50:      /* ps */
  3402.     pagestart = x;
  3403.     break;
  3404.       case 51:      /* pw */
  3405.     maxline = x;
  3406.     break;
  3407.       case 52:      /* qm */
  3408.     quiet_mode = x;
  3409.     break;
  3410.       case 53:      /* rw */
  3411.     rejoin = x;
  3412.     break;
  3413.       case 54:      /* s0 */
  3414.     strncpy(s0_init, cptr, sizeof(s0_init));
  3415.     break;
  3416.       case 55:      /* si */
  3417.     strncpy(stdin_name, cptr, sizeof(stdin_name));
  3418.     break;
  3419.       case 56:      /* so */
  3420.     make_sound = x;
  3421.     break;
  3422.       case 57:      /* sp */
  3423.     spool = x;
  3424.     pause_time = 0;
  3425.     break;
  3426.       case 58:      /* st */
  3427.     strncpy(stat_file, cptr, sizeof(stat_file));
  3428. #ifdef unix
  3429.     strlwr(stat_file);
  3430. #endif
  3431.     break;
  3432.       case 59:      /* td */
  3433.     strncpy(table_definition, cptr, 40);
  3434.     process_table_definition();
  3435.     break;
  3436.       case 60:      /* tf */
  3437.     strcpy(table_file, cptr);
  3438.     reload_table = TRUE;
  3439.     load_tables();
  3440.     break;
  3441.       case 61:      /* tm */
  3442.     trans_mode = x;
  3443.     break;
  3444.       case 62:      /* tn */
  3445.     trans_default = x;
  3446.     break;
  3447.       case 63:      /* tp */
  3448.     strcpy(transpath, cptr);
  3449.     break;
  3450.       case 64:      /* tv */
  3451.     timer = x;
  3452.     break;
  3453.       default:
  3454.     print_error("\7Improper option format: %s nothing follows =.\n", string);
  3455.       }        /* switch */
  3456.       break;
  3457.     }           /* option matched */
  3458.   }           /* j */
  3459.   if (options[j] == NULL)
  3460.   {           /* invalid */
  3461. invalid:
  3462.     fprintf(stderr, "\7Invalid option %s", string);
  3463.     if (total_lines)
  3464.       fprintf(stderr, " in line %ld", total_lines);
  3465.     print_error("\n");
  3466.   }           /* invalid */
  3467. }           /* process_options */
  3468.  
  3469. void process_table_definition()
  3470. {
  3471.   int j;
  3472.   if (!total_lines)
  3473.     print_error("\007td option not allowed on command line or nfbtrans.cnf\n");
  3474.   if (!table_definition[0])
  3475.     return;
  3476.   strlwr(table_definition);
  3477.   cols_in_table = chars_in_table = 0;
  3478.   strcpy(temp, table_definition);
  3479.   for (j = 0; temp[j]; j++)
  3480.   {
  3481.     if (temp[j] == '%')
  3482.     {           /* percent */
  3483.       if ((isdigit(temp[j + 1]) || ((temp[j + 1] == '-') &&
  3484.                     isdigit(temp[j + 2]))))
  3485.       {        /* field spec */
  3486.     if (cols_in_table >= 8)
  3487.       print_error("\007> 8 columns in line %ld\n",
  3488.               total_lines);
  3489.     j++;       /* index digit */
  3490.     field_width[cols_in_table] = get_integer(temp + j);
  3491.     if (field_width[cols_in_table] > MAX_COL_WIDTH)
  3492.       print_error("\007> %d characters in field %d of table definition in line %ld\n",
  3493.               MAX_COL_WIDTH, cols_in_table + 1, total_lines);
  3494.     chars_in_table += field_width[cols_in_table];
  3495.     if (temp[j] != 's')
  3496.       print_error("\007Invalid field specifier in %s\n",
  3497.               table_definition);
  3498.     cols_in_table++;
  3499.     continue;
  3500.       }        /* field spec */
  3501.       if (temp[j + 1] == '*')
  3502.     print_error("%s\n", "\007%* not allowed in table definition");
  3503.     }           /* percent */
  3504.     chars_in_table++;
  3505.   }           /* j */
  3506.   if (chars_in_table > curmax + margin - 1)
  3507.     print_error("\007Table definition > %d characters in line %ld\n",
  3508.         curmax + margin - 1, total_lines);
  3509.   flush_if_not_blank();
  3510. }           /* process_table_definition */
  3511.  
  3512. void trim(char *string)
  3513. {
  3514.   int i, l = strlen(string);
  3515. /*remove trailing cr lf and spaces*/
  3516.   for (i = l - 1; i >= 0; i--)
  3517.   {
  3518.     switch (string[i])
  3519.     {
  3520.     case ' ':
  3521.     case '\12':   /* lf */
  3522.     case '\15':   /* cr */
  3523.       break;
  3524.     default:
  3525.       string[i + 1] = 0;
  3526.       i = 0;
  3527.       while (string[i] == ' ')
  3528.     i++;
  3529.       if (i)
  3530.     strcpy(string, string + i);
  3531.       return;
  3532.     }
  3533.   }           /* i */
  3534. }           /* trim */
  3535.  
  3536. short strpos(char *string, char *substring)
  3537. {
  3538.   int i = 0, j, stringlen, sublen;
  3539.   stringlen = strlen(string);
  3540.   sublen = strlen(substring);
  3541.   if ((!stringlen) || (!sublen) || (sublen > stringlen))
  3542.     return (0);
  3543.   do
  3544.   {
  3545.     for (j = 0; j < sublen; j++)
  3546.       if (string[i + j] != substring[j])
  3547.     goto retry;
  3548.     return (short) (i + 1);
  3549. retry:;
  3550.   }
  3551.   while (++i < stringlen);
  3552.   return (0);
  3553. }           /* strpos */
  3554.  
  3555. void insert(char *ins, char *string)
  3556. {
  3557.   char buf[256];
  3558.   strcpy(buf, ins);
  3559.   strcat(buf, string);
  3560.   strcpy(string, buf);
  3561. }           /* insert */
  3562.  
  3563. void move(char *string1, char *string2, short bytes)
  3564. {
  3565.   while (bytes >= 0)
  3566.   {
  3567.     string2[bytes] = string1[bytes];
  3568.     bytes--;
  3569.   }           /* while */
  3570. }           /* move */
  3571.  
  3572. #ifdef DOS
  3573. void sort_names()
  3574. {           /* sorts names in file_names */
  3575.   short i, j;
  3576.   if (file_count < 2)
  3577.     return;       /* nothing to sort */
  3578.   for (i = 0; i < file_count; i++)
  3579.     for (j = (short) (i + 1); j < file_count; j++)
  3580.       if (strcmp(file_name[i], file_name[j]) > 0)
  3581.       {        /* out of order */
  3582.     strcpy(temp, file_name[i]);
  3583.     strcpy(file_name[i], file_name[j]);
  3584.     strcpy(file_name[j], temp);
  3585.       }        /* out of order */
  3586. }           /* sort_names */
  3587.  
  3588. #endif           /* DOS */
  3589.  
  3590. /***      Translate A File     ***/
  3591.  
  3592. void translate_file()
  3593. {
  3594.   short i, input_mode = 0, startfile;
  3595.   char *cptr;
  3596.   FILE *indirect_ptr = NULL;
  3597.   intext = NULL;   /* for statistics file */
  3598.   do
  3599.   {
  3600.     if (!stdin_tty)
  3601.       strcpy(inf_name, stdin_name);
  3602.     else
  3603.     {           /* input filename required */
  3604.       if (!input_file_arg)
  3605.       {        /* no file args */
  3606.     fprintf(stderr, "\nEnter source File name <RETURN> to exit? ");
  3607.     get_input(temp, 80);
  3608.     if (!temp[0])
  3609.       exit_program(0);
  3610.     strcpy(inf_name, temp);
  3611.     input_file_arg = (short) paramcount;
  3612.       }        /* no file args */
  3613.       else
  3614.       if (!indirect_ptr)
  3615.     strcpy(inf_name, paramstr[input_file_arg]);
  3616.       input_mode = 1;
  3617.       if (inf_name[0] == '@' && indirect_ptr == NULL)
  3618.       {        /* indirect mode */
  3619.     strcpy(inf_name, inf_name + 1); /* remove @ */
  3620.     indirect_ptr = fopen(inf_name, "r");
  3621.     if (!indirect_ptr)
  3622.       report_open_error();
  3623.     pagestart = 1;
  3624.       }        /* indirect mode */
  3625.  
  3626.       if (indirect_ptr)
  3627.     if (fgets(inf_name, 128, indirect_ptr))
  3628.     {       /* not eof */
  3629.       i = (short) (strlen(inf_name) - 1);
  3630.       if (i >= 0 && inf_name[i] == '\n')
  3631.         inf_name[i] = '\0';
  3632.       if (!i)
  3633.         continue;    /* skip blank lines */
  3634.     }       /* not eof */
  3635.     else
  3636.     {       /* eof */
  3637.       fclose(indirect_ptr);
  3638.       indirect_ptr = NULL;
  3639.       input_file_arg++;
  3640.       continue;
  3641.     }       /* eof */
  3642.  
  3643.       /* get length of path component of name */
  3644.       inf_path_len = 0;
  3645.       for (i = 0; inf_name[i]; i++)
  3646.     if (inf_name[i] == '\\' || inf_name[i] == '/' || inf_name[i] == ':')
  3647.       inf_path_len = (short) (i + 1);
  3648.       file_count = current_file = 0;
  3649.       startfile = 1;
  3650. #ifdef DOS
  3651.       if (strpbrk(inf_name, "?*"))
  3652.       {        /* wildcard chars */
  3653.     input_mode = 2; /* wildcard chars specified */
  3654.     pagestart = 1;
  3655.     cptr = strpbrk(inf_name, ",;");
  3656.     if (cptr)
  3657.     {       /* find startfile */
  3658.       *cptr = '\0'; /* remove startfile from filename */
  3659.       startfile = (short) atoi(cptr + 1);
  3660.       if (startfile < 1)
  3661.         startfile = 1;
  3662.     }       /* find startfile */
  3663.       }        /* wildcard chars */
  3664.       if (!_dos_findfirst(inf_name, 0, &fileinfo))
  3665.     do
  3666.     {       /* store and sort matching file names */
  3667.       if (test_extension(fileinfo.name) < 0)
  3668.         continue;    /* extension was excluded */
  3669.       strcpy(file_name[file_count++], fileinfo.name);
  3670.       if (file_count >= MAX_FILES)
  3671.         break; /* don't store any more */
  3672.     }
  3673.     while (!_dos_findnext(&fileinfo));
  3674.       if (!file_count)
  3675. /*no file was found in search but store name anyway*/
  3676.     strcpy(file_name[file_count++], inf_name + inf_path_len);
  3677.       sort_names();
  3678.       current_file = (short) (startfile - 1);
  3679.       if (current_file > file_count)
  3680.     break;
  3681.   get_next_file:
  3682.       strcpy(inf_name + inf_path_len, file_name[current_file++]);
  3683. #endif
  3684.     }           /* input filename required */
  3685.     total_lines = 0l;
  3686.     if (total_files)
  3687.     {
  3688.       lopactive = FALSE;
  3689.       l0[0] = l1[0] = '\0';
  3690.       get_config();
  3691.     }
  3692.     prog_init = test_extension(inf_name);
  3693.     if (prog_init < 0)
  3694.       print_error("\7%s: Excluded by ex= option\n", inf_name);
  3695.     hyp_ptr = NULL;
  3696.     if (stdin_tty)
  3697.     {           /* input filename required */
  3698.       inf_des = open_input_file();
  3699.       inf_des_save = inf_des;    /* in case the lf option is encountered */
  3700.       strncpy(hyphen_file, inf_name + inf_path_len, sizeof(hyphen_file));
  3701.       cptr = strpbrk(hyphen_file, ".");
  3702.       if (!cptr)
  3703.     cptr = hyphen_file + strlen(hyphen_file);
  3704.       strcpy(cptr, hyphen_extension);
  3705.       hyp_ptr = fopen(hyphen_file, "r");
  3706.       read_hyphen_file = (short) (hyp_ptr != (FILE *) NULL);
  3707.       if (spool > 1 && total_files > 0 && stdout_tty > 0)
  3708.     pause_program();
  3709.       if (ab_flag)
  3710.     break;
  3711.       if (skip_output == 0 && (indirect_ptr != NULL || input_mode == 2
  3712.                    || total_files > 0))
  3713.     fprintf(stderr, "Translating %s\n", inf_name);
  3714.       total_files++;
  3715.       fstat(inf_des, &infilestat);
  3716.       if (efl_mode && (infilestat.st_mode & IFCHR) == 0 && lopactive == FALSE)
  3717.       {        /* process .efl file */
  3718.     strcpy(efl_file, inf_name);
  3719.     cptr = strchr(efl_file, '.');
  3720.     if (!cptr)
  3721.       cptr = efl_file + strlen(efl_file);
  3722.     strlwr(cptr);
  3723.     if (strcmp(cptr, ".efl"))
  3724.     {       /* load */
  3725.       strcpy(cptr, ".EFL");
  3726.       strcpy(format_string, init[prog_init].format);
  3727.       load_template();
  3728.     }       /* load */
  3729.       }        /* process .efl file */
  3730.     }           /* input file required */
  3731.     get_date();    /* put date in date_string */
  3732.     if (leftmargin < 0)
  3733.     {           /* get left margin */
  3734.       leftmargin = 1;
  3735.       fprintf(stderr, "Enter Number of spaces before Left Margin of source File \n");
  3736.       fprintf(stderr, "     (usually 1)? %d", leftmargin);
  3737.       backspace_int(leftmargin);
  3738.       get_input(temp, 4);
  3739.       leftmargin = (short) atoi(temp);
  3740.       if (leftmargin <= 0)
  3741.     leftmargin = 1;
  3742.     }           /* get left margin */
  3743.     if (maxline <= 0)
  3744.     {           /* get maxline */
  3745.       maxline = 40;
  3746.       fprintf(stderr, "Enter Number of braille cells to emboss\n");
  3747.       fprintf(stderr, "  on a Line (usually 40)? %d", maxline);
  3748.       backspace_int(maxline);
  3749.       get_input(temp, 3);
  3750.       maxline = (short) atoi(temp);
  3751.       if (maxline <= 0)
  3752.     maxline = 40;
  3753.     }           /* get maxline */
  3754.     get_page_range();
  3755.     if (display_source < 0)
  3756.     {           /* display source? */
  3757.       fprintf(stderr, "\nDisplay Source Text (Y/N)? N\010");
  3758.       get_digit();
  3759.       if (temp[0] == 'y' || temp[0] == 'Y')
  3760.     display_source = TRUE;
  3761.       else
  3762.     display_source = FALSE;
  3763.     }           /* display source? */
  3764.     if (display_braille < 0)
  3765.     {           /* display braille? */
  3766.       fprintf(stderr, "\nDisplay Translated Text (Y/N)? Y\010");
  3767.       get_digit();
  3768.       if (temp[0] == 'n' || temp[0] == 'N')
  3769.     display_braille = FALSE;
  3770.     }           /* display braille? */
  3771.     if (linesperpage <= 0)
  3772.     {
  3773.       linesperpage = 25;
  3774.       fprintf(stderr, "\nNumber of Lines per Page? %d", linesperpage);
  3775.       backspace_int(linesperpage);
  3776.       get_input(temp, 5);
  3777.       if (temp[0])
  3778.     linesperpage = (short) atoi(temp);
  3779.       if (linesperpage <= 0)
  3780.     linesperpage = 25;
  3781.     }
  3782.     if (lineskips < 0)
  3783.     {
  3784.       lineskips = 99;
  3785.       fprintf(stderr, "Line Skips between Pages (99-FF, 999-VT)? %d", lineskips);
  3786.       backspace_int(lineskips);
  3787.       get_input(temp, 5);
  3788.       if (temp[0])
  3789.     lineskips = (short) atoi(temp);
  3790.       if (lineskips < 0)
  3791.     lineskips = 99;
  3792.     }
  3793.     if (current_file < 2)
  3794.       printit = TRUE;
  3795.     if (trans_mode < 10)
  3796.     {           /* get secondary translation mode */
  3797.       i = (short) (trans_default / 10);
  3798.       fprintf(stderr, "\nPlease select ");
  3799.       fprintf(stderr, "\n  1 to Translate and store in a File or");
  3800.       fprintf(stderr, "\n  2 Translate and emboss immediately.\n  Choice? %d",
  3801.           i);
  3802.       backspace_int(i);
  3803.       do
  3804.       {
  3805.     get_digit();
  3806.     if (!temp[0])
  3807.       i = (short) (trans_default / 10);
  3808.     else
  3809.       i = (short) atoi(temp);
  3810.       }
  3811.       while (i < 1 || i > 2);
  3812.     }           /* get secondary translation mode */
  3813.     else
  3814.       i = (short) (trans_mode / 10);
  3815.     trans_mode = (short) ((10 * i) + 1);
  3816.     if (i == 1)
  3817.     {           /* translate and store */
  3818.       printit = FALSE;
  3819.       if (!outf_name[0] && stdout_tty != 0)
  3820.       {        /* output file required */
  3821.     fprintf(stderr, "\nEnter name of File to create? ");
  3822.     get_input(outf_name, 48);
  3823.     if (!outf_name[0])
  3824.       exit_program(0);
  3825.       }        /* output file required */
  3826.     }           /* translate and store */
  3827.     if (!rejoin)
  3828.       rejoin = TRUE;
  3829.     xgrade = GRADE2;
  3830.     xformat = TEXT;
  3831.     find_toc_pages = FALSE;
  3832.     memset(toc_pages, 0, sizeof(toc_pages));
  3833.     current_pass = 1;
  3834.     if (spool > 0 && file_count >= 9 && printit)
  3835.       spool++;       /* pause between files so queue won't overflow */
  3836.     if ((printit && !(usr_default)))
  3837.       get_page_range();
  3838.     get_copies();
  3839.     if (printit == FALSE && stdout_tty != 0)
  3840.     {           /* disk file */
  3841.       if (test_file_exist())
  3842.     return;
  3843.       if (stdout_tty)
  3844.     printf("Writing to file - %s\n", outf_name);
  3845.     }           /* disk file */
  3846.     else
  3847.     {
  3848.       get_printer_file_name();
  3849.       if (total_files == 1)
  3850.     do_pause();
  3851.     }
  3852.     if (ab_flag)
  3853.       return;
  3854.     time(&time1);
  3855.     if (outf_name[0] && outf_des == 0)
  3856.       outf_des = open(outf_name, (int) (O_BINARY | O_CREAT | O_TRUNC | O_WRONLY), STD_OPEN);
  3857.     fstat(outf_des, &outfilestat);
  3858.     keep_control = 0;
  3859.     keep_together = keep_together_save = 0;
  3860.     total_lines = 0l;
  3861.     dopagenum = TRUE;
  3862.     strcpy(format_string, "~");
  3863.     strcpy(words, init[prog_init].pre_init);
  3864.     do_commands();
  3865.     strcpy(format_string, init[prog_init].format);
  3866.     if (xformat == AUTO_FORMAT)
  3867.       get_paragraph_type();
  3868.     if (printit && spool)
  3869.     {           /* printer ignore formfeed */
  3870.       strcpy(format_string, "~");
  3871.       strcpy(words, s0_init);
  3872.       do_commands();
  3873.       strcpy(format_string, init[prog_init].format);
  3874.     }           /* printer ignore formfeed */
  3875. #ifdef unix
  3876.     unbuf_stdin(); /* so we can check for esc */
  3877. #endif
  3878.  
  3879.     do
  3880.     {
  3881.       do_translate();
  3882.     }
  3883.     while (copies < lastcopy && ab_flag == 0);
  3884.     strcpy(format_string, "~");
  3885.     strcpy(words, init[prog_init].post_init);
  3886.     do_commands();
  3887.     in_length = filelength(inf_des);
  3888.     if (infilestat.st_mode & IFCHR)
  3889.       in_length = 0l;
  3890.     out_length = filelength(outf_des);
  3891.     close(inf_des);
  3892.     emboss_time = total_cells / (60l * (long) charspersec);
  3893.     write_stat_file();
  3894.     if (hyp_ptr)
  3895.       fclose(hyp_ptr);
  3896.     if (read_hyphen_file)
  3897.       unlink(hyphen_file);
  3898. #ifdef DOS
  3899.     if (printit && spool && ab_flag == 0)
  3900.     {           /* spool */
  3901.       if (stdout_tty)
  3902.       {        /* output not redirected */
  3903.     if (emboss_time > 1l)
  3904.       printf("Estimated embossing time: %ld minutes\n",
  3905.          emboss_time);
  3906.       }        /* output not redirected */
  3907.       close(outf_des);
  3908.       outf_des = 0;
  3909.       spool_file();
  3910.     }           /* spool */
  3911.     if (ab_flag)
  3912.       break;
  3913.     if (input_mode)
  3914.     {
  3915.       copies = 0;
  3916.       if (current_file < file_count)
  3917.     goto get_next_file;
  3918.     }
  3919. #endif           /* DOS */
  3920.     if (input_mode == 2)
  3921.     {           /* wildcards */
  3922.       input_mode = 1;
  3923.     }           /* wildcards */
  3924.     if (indirect_ptr)
  3925.       continue;
  3926.     input_file_arg++;
  3927.   }
  3928.   while (input_file_arg <= (short) paramcount);
  3929.   if (outf_des > 1)
  3930.     close(outf_des);
  3931.   if (intext)
  3932.     fclose(intext);
  3933.   fclose(conf_ptr);
  3934. }           /* translate_file */
  3935.  
  3936. int open_input_file()
  3937. {
  3938.   int h;
  3939.   h = open(inf_name, O_BINARY | O_RDONLY);
  3940.   if (h < 0)
  3941.     report_open_error();
  3942.   return (h);
  3943. }           /* open_input_file */
  3944.  
  3945. short test_file_exist()
  3946. {
  3947.   short retval = 0;
  3948.   if (access(outf_name, 0) == 0 && over_write == 0)
  3949.   {           /* file already exists */
  3950.     printf("\007File %s exists - Overwrite (Y/N)? Y\010", outf_name);
  3951.     get_digit();
  3952.     if (temp[0] == 'n' || temp[0] == 'N')
  3953.       retval = 1;
  3954.   }           /* file already exist */
  3955.   return (retval);
  3956. }           /* test_file_exist */
  3957.  
  3958. void report_open_error()
  3959. {
  3960.   if (errno == EACCES)
  3961.     print_error("\007%s is a directory\n", inf_name);
  3962.   else
  3963.     print_error("\7%s not found...\n", inf_name);
  3964. }           /* report_open_error */
  3965.  
  3966. void backtranslate_file()
  3967. {
  3968.   if (stdin_tty)
  3969.   {
  3970.     fprintf(stderr, "Enter file to back translate: ");
  3971.     get_input(temp, 80);
  3972.     if (!temp[0])
  3973.       exit_program(0);
  3974.     strcpy(inf_name, temp);
  3975.     inf_des = open(inf_name, O_BINARY | O_RDONLY);
  3976.     if (inf_des < 0)
  3977.       report_open_error();
  3978.   }
  3979.   else
  3980.     inf_des = 0;
  3981.   if (stdout_tty)
  3982.   {
  3983.     fprintf(stderr, "Enter file to Create: ");
  3984.     get_input(temp, 48);
  3985.     if (!temp[0])
  3986.       exit_program(0);
  3987.     strcpy(outf_name, temp);
  3988.     if (test_file_exist())
  3989.       return;
  3990.   }
  3991.   if (outf_name[0] && outf_des == 0)
  3992.     outf_des = open(outf_name, (int) (O_BINARY | O_CREAT | O_TRUNC | O_WRONLY), STD_OPEN);
  3993.   do
  3994.   {
  3995.     get_word();
  3996.     strupr(words);
  3997.   }
  3998.   while (!done);
  3999. }           /* backtranslate_file */
  4000.  
  4001. void spool_file()
  4002. {
  4003.   sprintf(temp, "print %s", outf_name);
  4004.   if (system(temp))
  4005.     print_error("\007Could not execute %s\n", temp);
  4006. }           /* spool_file */
  4007.  
  4008. short test_extension(char *string)
  4009. {
  4010.   short i, j = 0;
  4011.   char *cptr;
  4012.   /* get file extension */
  4013.   cptr = strchr(string, '.');
  4014.   if (cptr == NULL)
  4015.   {           /* no extension */
  4016.     for (i = 0; string[i]; i++)
  4017.       if (string[i] == ':' || string[i] == '\\' || string[i] == '/')
  4018.     j = (short) (i + 1);
  4019.     /* copy the filename without path component */
  4020.     strncpy(inf_name_ext, string + j, 8);
  4021.     j = search_extensions(inf_name_ext);
  4022.     if (j)
  4023.       goto done_test;
  4024.     cptr = string + strlen(string) - 1;
  4025.   }           /* no extension */
  4026.   strcpy(inf_name_ext, cptr + 1);
  4027.   /* find out if extension is in an ex= option */
  4028.   j = search_extensions(inf_name_ext);
  4029. done_test:
  4030.   if (j)
  4031.     return (prog_extension.prog_ext[j - 1].init_val);
  4032.   return (0);       /* for extensions not in ex= */
  4033. }           /* test_extension */
  4034.  
  4035. short search_extensions(char *string)
  4036. {
  4037.   short i, j = 0;
  4038.   strupr(string);
  4039.   for (i = 0; i < prog_extension.total; i++)
  4040.     if (!strcmp(string, prog_extension.prog_ext[i].ext))
  4041.       j = (short) (i + 1);    /* extension was in list */
  4042.   return (j);
  4043. }           /* search_extensions */
  4044.  
  4045. /*** Emboss a translated File ***/
  4046.  
  4047. void emboss_file()
  4048. {
  4049.   char ch, *cptr;
  4050.   if (!inf_name[0])
  4051.   {           /* get filename */
  4052.     printf("\nEnter the name of the already Translated File <RETURN> to exit: ");
  4053.     get_input(temp, 48);
  4054.     if (!temp[0])
  4055.       exit_program(0);
  4056.     strcpy(inf_name, temp);
  4057.   }           /* get filename */
  4058.   if ((intext = fopen(inf_name, FOPEN_READ)) == NULL)
  4059.     print_error("\7%s does not exist\n", inf_name);
  4060.   get_copies();
  4061.   get_page_range();
  4062.   usr_default = FALSE;
  4063.   printit = TRUE;
  4064.   get_date();
  4065.   get_printer_file_name();
  4066.   do_pause();
  4067.   if (ab_flag)
  4068.     return;
  4069.   outf_des = open(outf_name, O_BINARY | O_CREAT | O_TRUNC | O_WRONLY, S_IWRITE);
  4070.   do
  4071.   {           /* while there are copies to emboss */
  4072.     copies++;
  4073.     actualpage = 0;
  4074.     bpagec = 1;    /* current braille page */
  4075.     lineinct = 0;
  4076.     rewind(intext);/* start from beginning of file for this copy */
  4077.     while ((fgets(field, 80, intext)) && bpagec <= pageend)
  4078.     {           /* while there are lines to read and not passed ending
  4079.             * page */
  4080.       if (check_keyboard(0) < 0)
  4081.     break;
  4082.       lineinct++;
  4083.       linecount = (short) strlen(field);
  4084.       field[linecount - 1] = 0; /* remove \n */
  4085.       if ((cptr = strpbrk(field, "\013\014")) != NULL ||
  4086.       (short) lineinct > linesperpage)
  4087.       {        /* new page */
  4088.     bpagec++;  /* ff or vt */
  4089.     page_beep();
  4090.     if (!skip_output)
  4091.       fprintf(stderr, "Embossing page %d\n", bpagec);
  4092.     lineinct = 1;    /* first line on new page */
  4093.     if (bpagec > pageend)
  4094.       break;   /* done */
  4095.     if (display_braille > 0 && bpagec > pagestart && skip_output == 0)
  4096.     {       /* display braille */
  4097.       fprintf(stderr, "%s\n", field);
  4098.       if (linecount >= 20)
  4099.         fprintf(stderr, "       Copy %d of %d\n", copies, lastcopy);
  4100.     }       /* display_braille */
  4101.       }        /* new page */
  4102.       if (bpagec >= pagestart)
  4103.       {        /* process page */
  4104.     if (cptr)
  4105.     {       /* vt or ff */
  4106.       ch = *cptr;
  4107.       if (!skip_output)
  4108.         fprintf(stderr, "%s\n", field);
  4109.       strcpy(field, cptr + 1);
  4110.       if (actualpage)
  4111.         write_char(ch);
  4112.       actualpage++;
  4113.       delay(emboss_delay);
  4114.       if (field[0])
  4115.         write_string(field, 0);
  4116.     }       /* ff or vt */
  4117.     else
  4118.     {       /* no ff or vt */
  4119.       write_string(field, 1);
  4120.     }       /* no f or vt */
  4121.       }        /* process page */
  4122.     }           /* while */
  4123.   }
  4124.   while (copies < lastcopy);
  4125.   fclose(intext);
  4126.   close(outf_des);
  4127.   if (spool)
  4128.     spool_file();
  4129. }           /* emboss_file */
  4130.  
  4131. void get_page_range()
  4132. {
  4133.   char *cptr;
  4134.   if (pagestart <= 0)
  4135.   {           /* get starting page */
  4136.     pagestart = 1;
  4137.     fprintf(stderr, "Start at Page? 1\010");
  4138.     get_input(temp, 80);
  4139.     pagestart = (short) atoi(temp);
  4140.     cptr = strpbrk(temp, "-, ");
  4141.     if (cptr)
  4142.       pageend = (short) atoi(cptr + 1);
  4143.     if (pagestart <= 0)
  4144.       pagestart = 1;
  4145.   }           /* get starting page */
  4146.   /* if interpoint then pagestart should be odd */
  4147.   if (interpoint && (pagestart & 1) == 0)
  4148.     pagestart--;
  4149.   if (pageend < pagestart)
  4150.   {           /* pageend */
  4151.     pageend = 9999;
  4152.     fprintf(stderr, "Stop at Page (RETURN for end)? %d", pageend);
  4153.     backspace_int(pageend);
  4154.     get_input(temp, 5);
  4155.     pageend = (short) atoi(temp);
  4156.     if (!temp[0])
  4157.       pageend = 9999;
  4158.     if (pageend < 1)
  4159.       pageend = 9999;
  4160.   }           /* pageend */
  4161.   if (interpoint && (pageend & 1))
  4162.     pageend++;
  4163.   pagestart_save = pagestart;
  4164.   pageend_save = pageend;
  4165. }           /* get_page_range */
  4166.  
  4167. void get_copies()
  4168. {
  4169.   if (lastcopy <= 0)
  4170.   {
  4171.     lastcopy = 1;
  4172.     printf("\nNumber of Copies? %d\010", lastcopy);
  4173.     get_input(temp, 80);
  4174.     lastcopy = (short) atoi(temp);
  4175.     if (lastcopy <= 0)
  4176.       lastcopy = 1;
  4177.   }
  4178. }           /* get_copies */
  4179.  
  4180. void get_printer_file_name()
  4181. {
  4182.   int tries = 0;
  4183.   char *cptr;
  4184.   if (printit)
  4185.     if (stdout_tty)
  4186.     {           /* stdout is tty */
  4187.       if (!spool)
  4188.     strcpy(outf_name, prn);
  4189.       else
  4190.       {        /* spool */
  4191.     /* get location of temp file */
  4192.     cptr = (char *) getenv("TMP");
  4193.     if (cptr)
  4194.       strcpy(temp, cptr);
  4195.     else
  4196.       temp[0] = 0;
  4197.     do
  4198.     {
  4199.       tries++;
  4200.       sprintf(outf_name, "%s%02d%02d%02d", temp, tm->tm_hour, tm->tm_min,
  4201.           tm->tm_sec);
  4202.       if (!access(outf_name, 0))
  4203.         tm->tm_sec++;    /* file exists so use a different name */
  4204.       else
  4205.         break;
  4206.     }
  4207.     while (tries < 10);
  4208.  
  4209.     if (interpoint > 1)
  4210.       interpoint = 1;    /* don't eject blank page */
  4211.     printf("Creating %s\n", outf_name);
  4212.       }        /* spool */
  4213.     }           /* stdout is tty */
  4214. }           /* get_printer_file_name */
  4215.  
  4216. void do_pause()
  4217. {
  4218.   short i;
  4219.   if (pause_time && printit)
  4220.   {           /* pause */
  4221.     for (i = 0; i < pause_time; i++)
  4222.     {
  4223.       if (make_sound)
  4224. #ifdef DOS
  4225.     sound(440);
  4226.       delay(80);
  4227.       nosound();
  4228. #else           /* unix */
  4229.     beep(1);
  4230. #endif           /* DOS */
  4231.       delay(800);
  4232.       if (stdin_tty)
  4233.     if (check_keyboard(0) > 0)
  4234.       getch();
  4235.     }           /* i */
  4236.     skip_output = TRUE;
  4237.   }           /* pause */
  4238. }           /* do_pause */
  4239.  
  4240. void pause_program()
  4241. {
  4242.   if (emboss_time)
  4243.   {           /* pause */
  4244.     printf("Press any key to continue or wait %ld minutes for embossing\n",
  4245.        emboss_time);
  4246.     time1 = (long) time(NULL);
  4247.     do
  4248.     {
  4249.       if (check_keyboard(0))
  4250.     break;
  4251.     }
  4252.     while ((long) time(NULL) - time1 < emboss_time * 60l);
  4253.   }           /* pause */
  4254. }           /* pause_program */
  4255.  
  4256. short check_keyboard(short toggle)
  4257. {           /* returns -1 for esc 0 for no key and 1 otherwise */
  4258.   short i, retval = 0;
  4259.   if (kbhit())
  4260.   {           /* get key */
  4261.     i = (short) getch();
  4262.     if (i == 32 && toggle > 0)
  4263.       make_sound ^= TRUE;
  4264.     if (i == 27)
  4265.     {           /* escape */
  4266.       done = TRUE; /* abort */
  4267.       ab_flag = 1;
  4268.       retval = -1;
  4269.     }           /* escape */
  4270.     retval = 1;
  4271.   }           /* get key */
  4272.   return (retval);
  4273. }           /* check_keyboard */
  4274.  
  4275. void write_string(char *string, short display)
  4276. {
  4277.   int l;
  4278. #ifdef DOS
  4279.   l = sprintf(temp, "%s\r\n", string);
  4280. #else
  4281. #ifdef sysv
  4282.   l = sprintf(temp, "%s\n", string);
  4283. #else           /* not sysv */
  4284.   sprintf(temp, "%s\n", string);
  4285.   l = strlen(temp);
  4286. #endif           /* sysv */
  4287. #endif           /* DOS */
  4288.   if (write(outf_des, temp, l) < l)
  4289.     no_space();
  4290.   if (printit)
  4291.     delay(emboss_delay);
  4292.   if (display)
  4293.     if (display_braille && skip_output == FALSE)
  4294.       fprintf(stderr, "%s", temp);
  4295.   if (stat_file[0])
  4296.     add_dots(string);
  4297. }           /* write_string */
  4298.  
  4299. void write_char(char ch)
  4300. {
  4301.   if (write(outf_des, &ch, 1) <= 0)
  4302.     no_space();
  4303. }           /* write_char */
  4304.  
  4305. void no_space()
  4306. {
  4307.   short i;
  4308.   fprintf(stderr, "Error with output file: ");
  4309.   perror("Error");
  4310.   if (make_sound)
  4311.     for (i = 0; i < 5; i++)
  4312.     {
  4313. #ifdef DOS
  4314.       sound(750);
  4315.       delay(500);
  4316.       sound(1500);
  4317.       delay(500);
  4318. #else           /* unix */
  4319.       beep(2);
  4320. #endif           /* DOS */
  4321.     }
  4322. #ifdef DOS
  4323.   nosound();
  4324. #endif           /* DOS */
  4325.   exit_program(1);
  4326. }           /* no_space */
  4327.  
  4328. void copy_string(char *string1, char *string2, short maxlen)
  4329. {           /* copies at most length bytes of string2 into string1
  4330.             * accounting for escaped characters */
  4331.   short i, j = 0, k;
  4332.   for (i = 0; (string2[i] != '\0' && j < maxlen); i++)
  4333.     if (string2[i] != '\\')
  4334.       string1[j++] = string2[i];
  4335.     else
  4336.     {           /* escape */
  4337.       i++;       /* skip \ */
  4338.       if (isdigit(string2[i]))
  4339.       {        /* digit */
  4340.     k = (short) atoi(string2 + i);
  4341.     if (k > 9)
  4342.       i++;
  4343.     if (k > 99)
  4344.       i++;
  4345.     string1[j++] = (char) k;
  4346.       }        /* digit */
  4347.     }           /* escape */
  4348.   string1[j] = '\0';
  4349. }           /* copy_string */
  4350.  
  4351. void cleanup(int x)
  4352. {
  4353. #ifdef DOS
  4354.   setmode(1, O_TEXT);
  4355. #else           /* unix */
  4356.   restore_stdin();
  4357. #endif
  4358.   if (x == SIGINT)
  4359.     exit(0);
  4360. }           /* cleanup */
  4361.  
  4362. void exit_program(int x)
  4363. {
  4364.   cleanup(-1);
  4365.   exit(x);
  4366. }           /* exit_program */
  4367.  
  4368. void print_error(char *message,...)
  4369. {           /* prints message to stderr and exit program */
  4370.   long *ip = (long *) &message;
  4371.   fprintf(stderr, message, ip[1], ip[2], ip[3], ip[4], ip[5], ip[6]);
  4372.   exit_program(1);
  4373. }           /* print_error */
  4374.  
  4375. int ISalpha(char c)
  4376. {
  4377.   if (c < '\0')
  4378.   {
  4379.     if (rejoin & 8)
  4380.       return (1);
  4381.     return (0);
  4382.   }
  4383.   return (isalpha(c));
  4384. }           /* ISalpha */
  4385.  
  4386. void main(int argc, char *argv[])
  4387. {
  4388.   short i, j;
  4389.   paramcount = argc - 1;
  4390.   paramstr = argv;
  4391.   /* initialize structures */
  4392.   memset(init, 0, sizeof(init_t));
  4393.   memset(&prog_extension.total, 0, sizeof(prog_ext_t));
  4394.   stdin_tty = (short) isatty(0);
  4395.   stdout_tty = (short) isatty(1);
  4396. #ifdef unix
  4397.   save_stdin();
  4398.   get_tablename(table_file);
  4399.   if (stdout_tty)
  4400.     setbuf(stdout, NULL);    /* so printf always prints */
  4401. #else           /* msdos */
  4402.   strcpy(table_file, TABLENAME);
  4403. #endif           /* unix */
  4404.   get_config();
  4405.   signal(SIGINT, cleanup);
  4406.   if (no_copyright == FALSE)
  4407.   {           /* display message */
  4408.     fprintf(stderr, "\nNFBTRANS Grade Two Braille Translator - Release %s\n", VERSION);
  4409.     fprintf(stderr, "%s\012\012", COPYRIGHT);
  4410.   }           /* display message */
  4411.   load_tables();
  4412.  
  4413.   copies = 0;
  4414.   if (usr_default == FALSE && pagestart <= 1 && trans_mode <= 0)
  4415.   {           /* choose mode */
  4416.     j = (short) (trans_default % 10);
  4417.     fprintf(stderr, "\nPlease select\n");
  4418.     for (i = 0; i < max_menu; i++)
  4419.       fprintf(stderr, main_menu[i]);
  4420.     while (trans_mode % 10 < 1 || trans_mode % 10 > max_menu)
  4421.     {
  4422.       fprintf(stderr, "\nChoice? %d", j);
  4423.       backspace_int(j);
  4424. #ifdef DOS
  4425.       if (make_sound)
  4426.       {
  4427.     sound(440);
  4428.     delay(20);
  4429.     sound(1760);
  4430.     delay(20);
  4431.     nosound();
  4432.       }
  4433. #endif           /* DOS */
  4434.       get_digit();
  4435.       if (!temp[0])
  4436.     trans_mode = j;
  4437.       else
  4438.     trans_mode = (short) atoi(temp);
  4439.     }           /* while */
  4440.   }           /* choose mode */
  4441.   if ((trans_mode % 10) == 1 || usr_default == TRUE)
  4442.     translate_file();
  4443.   else
  4444.   {
  4445.     if ((trans_mode % 10) == 2)
  4446.       emboss_file();
  4447.     else
  4448.       backtranslate_file();
  4449.   }
  4450.   if (ab_flag)
  4451.     fprintf(
  4452.         stderr, "Program aborted\n");
  4453.   if (skip_output == TRUE && stdout_tty == TRUE)
  4454.   {
  4455.     do_pause();
  4456.     getch();
  4457.   }
  4458.   exit_program(0);
  4459. }           /* main */
  4460.